Initial commit from prod-batam

This commit is contained in:
mario
2025-05-27 10:51:12 +07:00
commit 025b96229b
3361 changed files with 304068 additions and 0 deletions

View File

@@ -0,0 +1,27 @@
import React from 'react';
import classNames from 'classnames';
import PropTypes from 'prop-types';
import Typography from '../Typography';
const Body = ({ text, className }) => {
const theme = 'bg-primary-dark';
return (
<div className={classNames('relative flex-auto', theme, className)}>
<Typography
variant="inherit"
color="initial"
className="text-[14px] !leading-[1.2]"
>
{text}
</Typography>
</div>
);
};
Body.propTypes = {
text: PropTypes.string,
className: PropTypes.string,
};
export default Body;

View File

@@ -0,0 +1,84 @@
import React, { useState } from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import Footer from './Footer';
import Body from './Body';
import Header from './Header';
import { useEffect } from 'react';
const Dialog = ({
title,
text,
onClose,
noCloseButton,
actions,
onShow,
onSubmit,
header: HeaderComponent = Header,
body: BodyComponent = Body,
footer: FooterComponent = Footer,
value: defaultValue = {},
}) => {
const [value, setValue] = useState(defaultValue);
const theme = 'bg-primary-dark';
const flex = 'flex flex-col';
const border = 'border-0 rounded';
const outline = 'outline-none focus:outline-none';
const position = 'relative';
const width = 'w-full';
const padding = 'px-[20px] pb-[20px] pt-[13px]';
useEffect(() => {
if (onShow) {
onShow();
}
}, [onShow]);
return (
<div className={classNames(theme, flex, border, outline, position, width, padding)}>
<HeaderComponent
title={title}
noCloseButton={noCloseButton}
onClose={onClose}
value={value}
setValue={setValue}
/>
<BodyComponent
text={text}
value={value}
setValue={setValue}
/>
<FooterComponent
actions={actions}
onSubmit={onSubmit}
value={value}
setValue={setValue}
/>
</div>
);
};
Dialog.propTypes = {
title: PropTypes.string,
text: PropTypes.string,
onClose: PropTypes.func,
noCloseButton: PropTypes.bool,
header: PropTypes.oneOfType([PropTypes.node, PropTypes.func]),
body: PropTypes.oneOfType([PropTypes.node, PropTypes.func]),
footer: PropTypes.oneOfType([PropTypes.node, PropTypes.func]),
onSubmit: PropTypes.func.isRequired,
value: PropTypes.object,
actions: PropTypes.arrayOf(
PropTypes.shape({
id: PropTypes.string.isRequired,
text: PropTypes.string.isRequired,
value: PropTypes.any,
type: PropTypes.oneOf(['primary', 'secondary', 'cancel']).isRequired,
})
).isRequired,
onShow: PropTypes.func,
};
export default Dialog;

View File

@@ -0,0 +1,50 @@
import React from 'react';
import classNames from 'classnames';
import PropTypes from 'prop-types';
import Button, { ButtonEnums } from '../Button';
const Footer = ({ actions = [], className, onSubmit = () => {}, value }) => {
const flex = 'flex items-center justify-end';
const padding = 'pt-[20px]';
return (
<div className={classNames(flex, padding, className)}>
{actions?.map((action, index) => {
const isFirst = index === 0;
const onClickHandler = event => onSubmit({ action, value, event });
return (
<Button
key={index}
name={action.text}
className={classNames({ 'ml-2': !isFirst }, action.classes)}
type={action.type}
onClick={onClickHandler}
>
{action.text}
</Button>
);
})}
</div>
);
};
const noop = () => {};
Footer.propTypes = {
className: PropTypes.string,
onSubmit: PropTypes.func.isRequired,
actions: PropTypes.arrayOf(
PropTypes.shape({
id: PropTypes.string.isRequired,
text: PropTypes.string.isRequired,
value: PropTypes.any,
type: PropTypes.oneOf([ButtonEnums.type.primary, ButtonEnums.type.secondary]).isRequired,
classes: PropTypes.arrayOf(PropTypes.string),
})
).isRequired,
};
export default Footer;

View File

@@ -0,0 +1,49 @@
import React from 'react';
import classNames from 'classnames';
import PropTypes from 'prop-types';
import Typography from '../Typography';
import Icon from '../Icon';
const CloseButton = ({ onClick }) => {
return (
<Icon
data-cy="close-button"
onClick={onClick}
name="close"
className="text-primary-active cursor-pointer"
/>
);
};
CloseButton.propTypes = {
onClick: PropTypes.func,
};
const Header = ({ title, noCloseButton = false, onClose }) => {
const theme = 'bg-primary-dark';
const flex = 'flex items-center justify-between';
const padding = 'pb-[20px]';
return (
<div className={classNames(theme, flex, padding)}>
<Typography
variant="h6"
color="primaryLight"
className="!leading-[1.2]"
>
{title}
</Typography>
{!noCloseButton && <CloseButton onClick={onClose} />}
</div>
);
};
Header.propTypes = {
className: PropTypes.string,
title: PropTypes.string,
noCloseButton: PropTypes.bool,
onClose: PropTypes.func,
};
export default Header;

View File

@@ -0,0 +1,73 @@
import Dialog from '../Dialog';
import { ArgsTable, Story, Canvas, Meta } from '@storybook/addon-docs';
import { createComponentTemplate } from '../../../storybook/functions/create-component-story';
export const argTypes = {
component: Dialog,
title: 'Modals/Dialog',
};
<Meta
title="Modals/Dialog"
component={Dialog}
/>
export const DialogTemplate = createComponentTemplate(Dialog);
<Heading
title="Dialog"
componentRelativePath="Dialog/Dialog.tsx"
/>
- [Overview](#overview)
- [Props](#props)
- [Usage](#usage)
- [Contribute](#contribute)
## Overview
Dialog is a modal dialog component which enabled to show a modal dialog.
<Canvas>
<Story name="Overview">{DialogTemplate.bind({})}</Story>
</Canvas>
## Props
<ArgsTable of={Dialog} />
## Usage
It can be used to show a modal dialog to submit a form or show a message.
<Canvas>
<Story
name="Submit"
args={{
title: 'Dialog Title',
text: 'Dialog Text',
onClose: () => {
window.alert('Dialog closed');
},
noCloseButton: false,
actions: [
{
id: 'cancel',
text: 'Cancel',
type: 'cancel',
},
{
id: 'submit',
text: 'Submit',
type: 'primary',
},
],
}}
>
{DialogTemplate.bind({})}
</Story>
</Canvas>
## Contribute
<Footer componentRelativePath="Dialog/__stories__/dialog.stories.mdx" />

View File

@@ -0,0 +1,2 @@
import Dialog from './Dialog';
export default Dialog;