fix: create custom hook and stepper to make multi-step modal functional
- Tambah custom hook 'use-query-state' dan implementasi stepper pada modal dengan tahapan lebih dari 1 - Hapus component ModalBackoffice karena sudah menggunakan component umum Modal
This commit is contained in:
@@ -7,36 +7,36 @@ interface IModalEditAccount {
|
||||
onClose: () => void;
|
||||
handleEditAccount?: () => void;
|
||||
currentStep?: number;
|
||||
nextStep: () => void;
|
||||
prevStep: () => void;
|
||||
resetStep: () => void;
|
||||
}
|
||||
|
||||
const ModalEditAccount = ({
|
||||
isOpen,
|
||||
onClose,
|
||||
currentStep,
|
||||
nextStep,
|
||||
prevStep,
|
||||
resetStep,
|
||||
handleEditAccount,
|
||||
currentStep = 1,
|
||||
}: IModalEditAccount) => {
|
||||
return (
|
||||
<Modal
|
||||
className="min-w-[400px] bg-primary-50 rounded-lg p-[40px] flex flex-col gap-8 text-center"
|
||||
isOpen={isOpen}
|
||||
onClose={onClose}
|
||||
onClose={() => {
|
||||
onClose();
|
||||
resetStep();
|
||||
}}
|
||||
disableEscapeKeyDown={true}
|
||||
>
|
||||
{currentStep === 1 && (
|
||||
<StepOne
|
||||
nextStep={() => {
|
||||
console.log('Next step');
|
||||
}}
|
||||
onClose={onClose}
|
||||
/>
|
||||
)}
|
||||
{currentStep === 1 && <StepOne nextStep={nextStep} onClose={onClose} />}
|
||||
{currentStep === 2 && (
|
||||
<StepTwo
|
||||
onClose={onClose}
|
||||
handleEditAccount={handleEditAccount}
|
||||
resetStep={() => {
|
||||
console.log('Reset step');
|
||||
}}
|
||||
resetStep={resetStep}
|
||||
/>
|
||||
)}
|
||||
</Modal>
|
||||
@@ -48,7 +48,7 @@ interface IStepOneProps {
|
||||
onClose: () => void;
|
||||
}
|
||||
|
||||
const StepOne = ({ nextStep, onClose }: IStepOneProps) => {
|
||||
const StepOne = ({ nextStep }: IStepOneProps) => {
|
||||
const [fullName, setFullName] = useState('Ahmad Wiyana');
|
||||
const [email, setEmail] = useState('fullname23@gmail.com');
|
||||
const [phoneNumber, setPhoneNumber] = useState('081904423804');
|
||||
@@ -136,7 +136,10 @@ const StepTwo = ({ onClose, handleEditAccount, resetStep }: IStepTwoProps) => (
|
||||
variant="bordered"
|
||||
size="lg"
|
||||
className="w-full"
|
||||
onClick={resetStep}
|
||||
onClick={() => {
|
||||
onClose();
|
||||
resetStep();
|
||||
}}
|
||||
>
|
||||
Batal
|
||||
</Button>
|
||||
@@ -146,6 +149,8 @@ const StepTwo = ({ onClose, handleEditAccount, resetStep }: IStepTwoProps) => (
|
||||
className="w-full"
|
||||
onClick={() => {
|
||||
handleEditAccount && handleEditAccount();
|
||||
onClose();
|
||||
resetStep();
|
||||
}}
|
||||
>
|
||||
Update
|
||||
|
||||
@@ -18,6 +18,7 @@ import {
|
||||
RowSelectionState,
|
||||
} from '@tanstack/react-table';
|
||||
import ModalEditAccount from './_components/modal-edit-account';
|
||||
import { useQueryState } from '../../hook/use-query-state';
|
||||
|
||||
interface Account {
|
||||
id: number;
|
||||
@@ -39,6 +40,17 @@ const mockData: Account[] = Array.from({ length: 90 }, (_, i) => ({
|
||||
export const Components: FC = (): ReactElement => {
|
||||
const [showModalEditAccount, setShowModalEditAccount] = useState(false);
|
||||
|
||||
const {
|
||||
step: currentStep,
|
||||
nextStep,
|
||||
prevStep,
|
||||
resetStep,
|
||||
} = useQueryState('step', {
|
||||
defaultValue: 1,
|
||||
maxValue: 2,
|
||||
minValue: 1,
|
||||
});
|
||||
|
||||
const [pagination, setPagination] = React.useState<PaginationState>({
|
||||
pageIndex: 0,
|
||||
pageSize: 9,
|
||||
@@ -166,11 +178,15 @@ export const Components: FC = (): ReactElement => {
|
||||
|
||||
{/* Modal Edit Account */}
|
||||
<ModalEditAccount
|
||||
currentStep={currentStep}
|
||||
isOpen={showModalEditAccount}
|
||||
onClose={() => setShowModalEditAccount(false)}
|
||||
handleEditAccount={() => {
|
||||
console.log('Account updated');
|
||||
}}
|
||||
nextStep={nextStep}
|
||||
prevStep={prevStep}
|
||||
resetStep={resetStep}
|
||||
/>
|
||||
</Fragment>
|
||||
);
|
||||
|
||||
@@ -6,49 +6,47 @@ interface IModalAddItem {
|
||||
onClose: () => void;
|
||||
handleAddItem: () => void;
|
||||
currentStep?: number;
|
||||
nextStep: () => void;
|
||||
prevStep: () => void;
|
||||
resetStep: () => void;
|
||||
}
|
||||
|
||||
const ModalAddItem = ({
|
||||
isOpen,
|
||||
onClose,
|
||||
currentStep,
|
||||
nextStep,
|
||||
resetStep,
|
||||
handleAddItem,
|
||||
currentStep = 1,
|
||||
}: IModalAddItem) => {
|
||||
return (
|
||||
<Modal
|
||||
className="min-w-[400px] bg-primary-50 rounded-lg p-[40px] flex flex-col gap-8 text-center"
|
||||
isOpen={isOpen}
|
||||
onClose={onClose}
|
||||
onClose={() => {
|
||||
onClose();
|
||||
resetStep();
|
||||
}}
|
||||
disableEscapeKeyDown={true}
|
||||
>
|
||||
{currentStep === 1 && (
|
||||
<StepOne
|
||||
nextStep={() => {
|
||||
console.log('Next step');
|
||||
}}
|
||||
onClose={onClose}
|
||||
/>
|
||||
)}
|
||||
{currentStep === 1 && <StepOne nextStep={nextStep} onClose={onClose} />}
|
||||
{currentStep === 2 && (
|
||||
<StepTwo
|
||||
onClose={onClose}
|
||||
handleAddItem={handleAddItem}
|
||||
resetStep={() => {
|
||||
console.log('Reset step');
|
||||
}}
|
||||
resetStep={resetStep}
|
||||
/>
|
||||
)}
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
||||
// TODO: Functional stepper
|
||||
interface IStepOneProps {
|
||||
nextStep: () => void;
|
||||
onClose: () => void;
|
||||
}
|
||||
|
||||
const StepOne = ({ nextStep, onClose }: IStepOneProps) => (
|
||||
const StepOne = ({ nextStep }: IStepOneProps) => (
|
||||
<>
|
||||
<Modal.Header>
|
||||
<h2 className="text-p1 font-semibold text-primary-500 mb-3">
|
||||
@@ -83,7 +81,7 @@ const StepOne = ({ nextStep, onClose }: IStepOneProps) => (
|
||||
/>
|
||||
</div>
|
||||
|
||||
<Button variant="primary" size="lg" className="w-full">
|
||||
<Button variant="primary" size="lg" className="w-full" onClick={nextStep}>
|
||||
Tambahkan Item
|
||||
</Button>
|
||||
</Modal.Content>
|
||||
@@ -92,8 +90,8 @@ const StepOne = ({ nextStep, onClose }: IStepOneProps) => (
|
||||
|
||||
interface IStepTwoProps {
|
||||
onClose: () => void;
|
||||
resetStep: () => void;
|
||||
handleAddItem?: () => void;
|
||||
resetStep: () => void;
|
||||
}
|
||||
|
||||
const StepTwo = ({ onClose, handleAddItem, resetStep }: IStepTwoProps) => (
|
||||
@@ -112,7 +110,10 @@ const StepTwo = ({ onClose, handleAddItem, resetStep }: IStepTwoProps) => (
|
||||
variant="bordered"
|
||||
size="lg"
|
||||
className="w-full"
|
||||
onClick={resetStep}
|
||||
onClick={() => {
|
||||
onClose();
|
||||
resetStep();
|
||||
}}
|
||||
>
|
||||
Batal
|
||||
</Button>
|
||||
@@ -122,6 +123,8 @@ const StepTwo = ({ onClose, handleAddItem, resetStep }: IStepTwoProps) => (
|
||||
className="w-full"
|
||||
onClick={() => {
|
||||
handleAddItem && handleAddItem();
|
||||
onClose();
|
||||
resetStep();
|
||||
}}
|
||||
>
|
||||
Tambahkan
|
||||
|
||||
@@ -6,35 +6,35 @@ interface IModalEditItem {
|
||||
onClose: () => void;
|
||||
handleEditItem?: () => void;
|
||||
currentStep?: number;
|
||||
nextStep: () => void;
|
||||
prevStep: () => void;
|
||||
resetStep: () => void;
|
||||
}
|
||||
|
||||
const ModalEditItem = ({
|
||||
isOpen,
|
||||
onClose,
|
||||
currentStep,
|
||||
nextStep,
|
||||
resetStep,
|
||||
handleEditItem,
|
||||
currentStep = 1,
|
||||
}: IModalEditItem) => {
|
||||
return (
|
||||
<Modal
|
||||
className="min-w-[400px] bg-primary-50 rounded-lg p-[40px] flex flex-col gap-8 text-center"
|
||||
isOpen={isOpen}
|
||||
onClose={onClose}
|
||||
onClose={() => {
|
||||
onClose();
|
||||
resetStep();
|
||||
}}
|
||||
disableEscapeKeyDown={true}
|
||||
>
|
||||
{currentStep === 1 && (
|
||||
<StepOne
|
||||
nextStep={() => {
|
||||
console.log('Next step');
|
||||
}}
|
||||
onClose={onClose}
|
||||
/>
|
||||
)}
|
||||
{currentStep === 1 && <StepOne nextStep={nextStep} onClose={onClose} />}
|
||||
{currentStep === 2 && (
|
||||
<StepTwo
|
||||
onClose={onClose}
|
||||
resetStep={() => {
|
||||
console.log('Reset step');
|
||||
}}
|
||||
handleEditItem={handleEditItem}
|
||||
resetStep={resetStep}
|
||||
/>
|
||||
)}
|
||||
</Modal>
|
||||
@@ -46,7 +46,7 @@ interface IStepOneProps {
|
||||
onClose: () => void;
|
||||
}
|
||||
|
||||
const StepOne = ({ nextStep, onClose }: IStepOneProps) => (
|
||||
const StepOne = ({ nextStep }: IStepOneProps) => (
|
||||
<>
|
||||
<Modal.Header>
|
||||
<h2 className="text-p1 font-semibold text-primary-500 mb-3">
|
||||
@@ -110,7 +110,10 @@ const StepTwo = ({ onClose, handleEditItem, resetStep }: IStepTwoProps) => (
|
||||
variant="bordered"
|
||||
size="lg"
|
||||
className="w-full"
|
||||
onClick={resetStep}
|
||||
onClick={() => {
|
||||
onClose();
|
||||
resetStep();
|
||||
}}
|
||||
>
|
||||
Batal
|
||||
</Button>
|
||||
@@ -120,6 +123,8 @@ const StepTwo = ({ onClose, handleEditItem, resetStep }: IStepTwoProps) => (
|
||||
className="w-full"
|
||||
onClick={() => {
|
||||
handleEditItem && handleEditItem();
|
||||
onClose();
|
||||
resetStep();
|
||||
}}
|
||||
>
|
||||
Update
|
||||
|
||||
@@ -10,12 +10,24 @@ import { FC, Fragment, ReactElement, useState } from 'react';
|
||||
import ModalAddItem from './_components/modal-add-item';
|
||||
import ModalEditItem from './_components/modal-edit-item';
|
||||
import ModalDeleteItem from './_components/modal-delete-item';
|
||||
import { useQueryState } from '../../hook/use-query-state';
|
||||
|
||||
export const Components: FC = (): ReactElement => {
|
||||
const [showModalAddItem, setShowModalAddItem] = useState(false);
|
||||
const [showModalEditItem, setShowModalEditItem] = useState(false);
|
||||
const [showModalDeleteItem, setShowModalDeleteItem] = useState(false);
|
||||
|
||||
const {
|
||||
step: currentStep,
|
||||
nextStep,
|
||||
prevStep,
|
||||
resetStep,
|
||||
} = useQueryState('step', {
|
||||
defaultValue: 1,
|
||||
maxValue: 2,
|
||||
minValue: 1,
|
||||
});
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<main className="w-full px-[48px] py-[40px] flex flex-col gap-8">
|
||||
@@ -159,20 +171,28 @@ export const Components: FC = (): ReactElement => {
|
||||
|
||||
{/* Modal Add Item */}
|
||||
<ModalAddItem
|
||||
currentStep={currentStep}
|
||||
isOpen={showModalAddItem}
|
||||
onClose={() => setShowModalAddItem(false)}
|
||||
handleAddItem={() => {
|
||||
console.log('Item added');
|
||||
}}
|
||||
nextStep={nextStep}
|
||||
prevStep={prevStep}
|
||||
resetStep={resetStep}
|
||||
/>
|
||||
|
||||
{/* Modal Edit Item */}
|
||||
<ModalEditItem
|
||||
currentStep={currentStep}
|
||||
isOpen={showModalEditItem}
|
||||
onClose={() => setShowModalEditItem(false)}
|
||||
handleEditItem={() => {
|
||||
console.log('Item edited');
|
||||
}}
|
||||
nextStep={nextStep}
|
||||
prevStep={prevStep}
|
||||
resetStep={resetStep}
|
||||
/>
|
||||
|
||||
{/* Modal Delete Item */}
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
import { useCallback, useEffect, useState } from 'react';
|
||||
|
||||
interface UseQueryStateOptions {
|
||||
defaultValue: number;
|
||||
maxValue?: number;
|
||||
minValue?: number;
|
||||
}
|
||||
|
||||
export const useQueryState = (key: string, options: UseQueryStateOptions) => {
|
||||
const { defaultValue, maxValue = Infinity, minValue = 1 } = options;
|
||||
|
||||
const getQueryParam = (param: string): string | null => {
|
||||
if (typeof window === 'undefined') return null;
|
||||
const searchParams = new URLSearchParams(window.location.search);
|
||||
return searchParams.get(param);
|
||||
};
|
||||
|
||||
const setQueryParam = (param: string, value: string) => {
|
||||
const searchParams = new URLSearchParams(window.location.search);
|
||||
searchParams.set(param, value);
|
||||
const newUrl = `${window.location.pathname}?${searchParams.toString()}`;
|
||||
window.history.replaceState(null, '', newUrl);
|
||||
};
|
||||
|
||||
const initialValue = () => {
|
||||
const queryValue = getQueryParam(key);
|
||||
const parsedValue = queryValue ? parseInt(queryValue, 10) : defaultValue;
|
||||
return Math.max(minValue, Math.min(maxValue, parsedValue));
|
||||
};
|
||||
|
||||
const [value, setValue] = useState<number>(initialValue);
|
||||
|
||||
useEffect(() => {
|
||||
const handlePopState = () => {
|
||||
const queryValue = getQueryParam(key);
|
||||
const newValue = queryValue ? parseInt(queryValue, 10) : defaultValue;
|
||||
setValue(Math.max(minValue, Math.min(maxValue, newValue)));
|
||||
};
|
||||
|
||||
window.addEventListener('popstate', handlePopState);
|
||||
return () => window.removeEventListener('popstate', handlePopState);
|
||||
}, [key, defaultValue, minValue, maxValue]);
|
||||
|
||||
const updateValue = useCallback(
|
||||
(newValue: number) => {
|
||||
const constrainedValue = Math.max(minValue, Math.min(maxValue, newValue));
|
||||
setValue(constrainedValue);
|
||||
setQueryParam(key, constrainedValue.toString());
|
||||
},
|
||||
[key, minValue, maxValue]
|
||||
);
|
||||
|
||||
const nextStep = useCallback(() => {
|
||||
updateValue(value + 1);
|
||||
}, [value, updateValue]);
|
||||
|
||||
const prevStep = useCallback(() => {
|
||||
updateValue(value - 1);
|
||||
}, [value, updateValue]);
|
||||
|
||||
const resetStep = useCallback(() => {
|
||||
updateValue(defaultValue);
|
||||
}, [defaultValue, updateValue]);
|
||||
|
||||
return {
|
||||
step: value,
|
||||
nextStep,
|
||||
prevStep,
|
||||
resetStep,
|
||||
};
|
||||
};
|
||||
@@ -1 +0,0 @@
|
||||
export * from './modal-backoffice';
|
||||
@@ -1,25 +0,0 @@
|
||||
import { ReactElement, ReactNode } from 'react';
|
||||
|
||||
interface ModalBackofficeProps {
|
||||
children: ReactNode;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
export const ModalBackoffice = ({
|
||||
children,
|
||||
className,
|
||||
...rest
|
||||
}: ModalBackofficeProps): ReactElement => {
|
||||
return (
|
||||
<div
|
||||
className={`w-[400px] bg-primary-50 rounded-lg p-[40px] gap-[32px] ${
|
||||
className || ''
|
||||
}`}
|
||||
{...rest}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ModalBackoffice;
|
||||
@@ -1,373 +0,0 @@
|
||||
import type { Meta, StoryObj } from '@storybook/react';
|
||||
import { ModalBackoffice } from './modal-backoffice';
|
||||
import { InputForm } from '../../molecules';
|
||||
import { Button } from '../../atoms';
|
||||
|
||||
const meta: Meta<typeof ModalBackoffice> = {
|
||||
title: 'Organisms/Modal Backoffice',
|
||||
component: ModalBackoffice,
|
||||
tags: ['autodocs'],
|
||||
parameters: {
|
||||
layout: 'centered',
|
||||
},
|
||||
} satisfies Meta<typeof ModalBackoffice>;
|
||||
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof ModalBackoffice>;
|
||||
|
||||
export const Default: Story = {
|
||||
args: {
|
||||
// isOpen: true,
|
||||
// onClose: () => console.log('Modal closed'),
|
||||
// title: 'Sample Modal',
|
||||
children: (
|
||||
<>
|
||||
<h2 className="text-p1 font-semibold text-primary-500 mb-3">
|
||||
Modal Title
|
||||
</h2>
|
||||
<p className="text-p3 text-neutral-400">
|
||||
Lorem ipsum dolor sit amet consectetur adipisicing elit. Quas repellat
|
||||
rerum doloremque dolorem fugit architecto eos blanditiis ratione
|
||||
facere? Esse dolores inventore deleniti. Dicta voluptatem dolore vel
|
||||
quia amet dolorem?
|
||||
</p>
|
||||
<div className="flex flex-col gap-4"></div>
|
||||
</>
|
||||
),
|
||||
},
|
||||
};
|
||||
|
||||
export const TambahItemGacha: Story = {
|
||||
args: {
|
||||
children: (
|
||||
<div className="flex flex-col gap-8">
|
||||
<div>
|
||||
<h2 className="text-p1 font-semibold text-primary-500 mb-3">
|
||||
Tambah Item Gacha
|
||||
</h2>
|
||||
<p className="text-p3 text-neutral-400">
|
||||
Lengkapi detail di bawah ini untuk menambahkan item gacha
|
||||
</p>
|
||||
</div>
|
||||
<div className="flex flex-col gap-4">
|
||||
<InputForm
|
||||
label="Nama Hadiah"
|
||||
type="text"
|
||||
placeholder="Masukkan Nama Hadiah"
|
||||
size="lg"
|
||||
className="w-full"
|
||||
/>
|
||||
<InputForm
|
||||
label="Chance Rate"
|
||||
type="text"
|
||||
placeholder="Masukkan Chance Rate"
|
||||
size="lg"
|
||||
className="w-full"
|
||||
/>
|
||||
<InputForm
|
||||
label="Foto Barang"
|
||||
type="text"
|
||||
placeholder=".jpg, .jpeg, atau .png"
|
||||
size="lg"
|
||||
className="w-full"
|
||||
/>
|
||||
</div>
|
||||
<Button variant="primary" size="lg" className="w-full">
|
||||
Tambahkan Item
|
||||
</Button>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
};
|
||||
|
||||
export const TambahItem: Story = {
|
||||
args: {
|
||||
children: (
|
||||
<div className="flex flex-col gap-8 text-center">
|
||||
<div>
|
||||
<h2 className="text-p1 font-semibold text-primary-500 mb-3">
|
||||
Tambah Item
|
||||
</h2>
|
||||
<p className="text-p3 text-neutral-400">
|
||||
Apakah kamu yakin ingin
|
||||
<br /> menambahkan item ini?
|
||||
</p>
|
||||
</div>
|
||||
<div className="flex gap-4">
|
||||
<Button variant="bordered" size="lg" className="w-full">
|
||||
Batal
|
||||
</Button>
|
||||
<Button variant="primary" size="lg" className="w-full">
|
||||
Tambahkan
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
};
|
||||
|
||||
export const EditItemGacha: Story = {
|
||||
args: {
|
||||
children: (
|
||||
<div className="flex flex-col gap-8">
|
||||
<div>
|
||||
<h2 className="text-p1 font-semibold text-primary-500 mb-3">
|
||||
Edit Item Gacha
|
||||
</h2>
|
||||
<p className="text-p3 text-neutral-400">
|
||||
Silakan mengubah detail dari item yang diperlukan
|
||||
</p>
|
||||
</div>
|
||||
<div className="flex flex-col gap-4">
|
||||
<InputForm
|
||||
label="Nama Hadiah"
|
||||
type="text"
|
||||
placeholder="Masukkan Nama Hadiah"
|
||||
size="lg"
|
||||
className="w-full"
|
||||
/>
|
||||
<InputForm
|
||||
label="Chance Rate"
|
||||
type="text"
|
||||
placeholder="Masukkan Chance Rate"
|
||||
size="lg"
|
||||
className="w-full"
|
||||
/>
|
||||
<InputForm
|
||||
label="Foto Barang"
|
||||
type="text"
|
||||
placeholder=".jpg, .jpeg, atau .png"
|
||||
size="lg"
|
||||
className="w-full"
|
||||
/>
|
||||
</div>
|
||||
<Button variant="primary" size="lg" className="w-full">
|
||||
Perbarui Item
|
||||
</Button>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
};
|
||||
|
||||
export const UpdateItem: Story = {
|
||||
args: {
|
||||
children: (
|
||||
<div className="flex flex-col gap-8 text-center">
|
||||
<div>
|
||||
<h2 className="text-p1 font-semibold text-primary-500 mb-3">
|
||||
Update Item
|
||||
</h2>
|
||||
<p className="text-p3 text-neutral-400">
|
||||
Apakah kamu yakin dengan
|
||||
<br /> perubahan yang dilakukan?
|
||||
</p>
|
||||
</div>
|
||||
<div className="flex gap-4">
|
||||
<Button variant="bordered" size="lg" className="w-full">
|
||||
Batal
|
||||
</Button>
|
||||
<Button variant="primary" size="lg" className="w-full">
|
||||
Update
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
};
|
||||
|
||||
export const DeleteItem: Story = {
|
||||
args: {
|
||||
children: (
|
||||
<div className="flex flex-col gap-8 text-center">
|
||||
<img
|
||||
src="/chibi-delete.webp"
|
||||
alt="Delete item?"
|
||||
width={148}
|
||||
className="self-center"
|
||||
/>
|
||||
<div>
|
||||
<h2 className="text-p1 font-semibold text-danger-500 mb-3">
|
||||
Delete Item
|
||||
</h2>
|
||||
<p className="text-p3 text-neutral-400">
|
||||
Apakah kamu yakin untuk menghapus item ini?
|
||||
</p>
|
||||
</div>
|
||||
<div className="flex gap-4">
|
||||
<Button variant="secondary" size="lg" className="w-full">
|
||||
Batal Hapus
|
||||
</Button>
|
||||
<Button variant="danger" size="lg" className="w-full">
|
||||
Hapus Item
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
};
|
||||
|
||||
export const EditDataAkun: Story = {
|
||||
args: {
|
||||
children: (
|
||||
<div className="flex flex-col gap-8">
|
||||
<h2 className="text-p1 font-semibold text-primary-500 mb-3">
|
||||
Edit Data Akun
|
||||
</h2>
|
||||
|
||||
<div className="flex flex-col gap-4">
|
||||
<InputForm
|
||||
label="Nama Lengkap"
|
||||
type="text"
|
||||
placeholder="Masukkan Nama Lengkap"
|
||||
value="Ahmad Wiyana"
|
||||
size="lg"
|
||||
className="w-full"
|
||||
/>
|
||||
<InputForm
|
||||
label="Email"
|
||||
type="text"
|
||||
placeholder="Masukkan Email"
|
||||
value="fullname23@gmail.com"
|
||||
size="lg"
|
||||
className="w-full"
|
||||
/>
|
||||
<InputForm
|
||||
label="Nomor Telepon"
|
||||
type="text"
|
||||
placeholder="Masukkan Nomor Telepon"
|
||||
value="081904423804"
|
||||
size="lg"
|
||||
className="w-full"
|
||||
/>
|
||||
<InputForm
|
||||
label="Alamat"
|
||||
type="text"
|
||||
placeholder="Masukkan Alamat"
|
||||
value="Jl. Pantai Cibaduyut Indah"
|
||||
size="lg"
|
||||
className="w-full"
|
||||
/>
|
||||
</div>
|
||||
<Button variant="primary" size="lg" className="w-full">
|
||||
Perbarui Data
|
||||
</Button>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
};
|
||||
|
||||
export const UpdateDataAkun: Story = {
|
||||
args: {
|
||||
children: (
|
||||
<div className="flex flex-col gap-8 text-center">
|
||||
<div>
|
||||
<h2 className="text-p1 font-semibold text-primary-500 mb-3">
|
||||
Update Data
|
||||
</h2>
|
||||
<p className="text-p3 text-neutral-400">
|
||||
Apakah kamu yakin dengan
|
||||
<br /> perubahan yang dilakukan?
|
||||
</p>
|
||||
</div>
|
||||
<div className="flex gap-4">
|
||||
<Button variant="bordered" size="lg" className="w-full">
|
||||
Batal
|
||||
</Button>
|
||||
<Button variant="primary" size="lg" className="w-full">
|
||||
Update
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
};
|
||||
|
||||
export const ValidasiTransaksi: Story = {
|
||||
args: {
|
||||
children: (
|
||||
<div className="flex flex-col gap-8">
|
||||
<h2 className="text-p1 font-semibold text-primary-500 ">
|
||||
Validasi Transaksi
|
||||
</h2>
|
||||
|
||||
<InputForm
|
||||
label="Nomor Transaksi"
|
||||
type="text"
|
||||
placeholder="Masukkan Nomor Transaksi"
|
||||
value="2502133Y9AFVBO"
|
||||
size="lg"
|
||||
className="w-full"
|
||||
/>
|
||||
<div className="flex gap-4">
|
||||
<Button
|
||||
variant="bordered"
|
||||
size="lg"
|
||||
className="w-full border-danger-500 text-danger-500 hover:border-danger-700 hover:text-danger-700"
|
||||
>
|
||||
Tidak Valid
|
||||
</Button>
|
||||
<Button variant="primary" size="lg" className="w-full">
|
||||
Valid
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
};
|
||||
|
||||
export const ProsesDelivery: Story = {
|
||||
args: {
|
||||
children: (
|
||||
<div className="flex flex-col gap-8">
|
||||
<div>
|
||||
<h2 className="text-p1 font-semibold text-primary-500 mb-3">
|
||||
Delivery Process
|
||||
</h2>
|
||||
|
||||
<p className="text-p3 text-neutral-400">
|
||||
Lakukan pengiriman hadiah gacha untuk pengguna di bawah ini, jika
|
||||
sudah ubah status menjadi “Delivered”.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col gap-4">
|
||||
<InputForm
|
||||
label="Nama Lengkap"
|
||||
type="text"
|
||||
placeholder="Masukkan Nama Lengkap"
|
||||
value="Ahmad Wiyana"
|
||||
size="lg"
|
||||
className="w-full"
|
||||
/>
|
||||
<InputForm
|
||||
label="Item yang didapatkan"
|
||||
type="text"
|
||||
placeholder="Masukkan Nama Item"
|
||||
value="Lanyard + ID Card"
|
||||
size="lg"
|
||||
className="w-full"
|
||||
/>
|
||||
<InputForm
|
||||
label="Alamat Pengiriman"
|
||||
type="text"
|
||||
placeholder="Masukkan Alamat Pengiriman"
|
||||
value="Jl. Pantai Cibaduyut Indah"
|
||||
size="lg"
|
||||
className="w-full"
|
||||
/>
|
||||
<InputForm
|
||||
label="Status"
|
||||
type="text"
|
||||
placeholder="Isi Status Pengiriman"
|
||||
value="Lanyard + ID Card"
|
||||
size="lg"
|
||||
className="w-full"
|
||||
/>
|
||||
</div>
|
||||
<Button variant="primary" size="lg" className="w-full">
|
||||
Tambahkan Item
|
||||
</Button>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
};
|
||||
Reference in New Issue
Block a user