feat: slicing modal for backoffice 'data pengiriman hadiah' page

This commit is contained in:
Hafid Nur
2025-03-31 17:32:30 +07:00
parent ecec423d30
commit 3b979119ed
2 changed files with 227 additions and 150 deletions
@@ -0,0 +1,71 @@
import { Button } from '@imphnen-frontend-service/ui/atoms';
import { InputForm, Modal } from '@imphnen-frontend-service/ui/molecules';
interface IModalProcessDelivery {
isOpen: boolean;
onClose: () => void;
onProcessDelivery?: () => void;
}
const ModalProcessDelivery = ({ isOpen, onClose }: IModalProcessDelivery) => {
return (
<Modal
className="min-w-[400px] bg-primary-50 rounded-lg p-[40px] flex flex-col gap-8 text-center"
isOpen={isOpen}
onClose={onClose}
disableEscapeKeyDown={true}
>
<Modal.Header>
<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>
</Modal.Header>
<Modal.Content className="flex flex-col gap-8">
<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">
Proses Pengiriman
</Button>
</Modal.Content>
</Modal>
);
};
export default ModalProcessDelivery;
+39 -33
View File
@@ -1,6 +1,6 @@
import * as React from 'react'; import * as React from 'react';
import { FC, ReactElement, useState } from 'react'; import { FC, Fragment, ReactElement, useState } from 'react';
import { import {
FilterOutlined, FilterOutlined,
SearchOutlined, SearchOutlined,
@@ -17,13 +17,15 @@ import {
useReactTable, useReactTable,
RowSelectionState, RowSelectionState,
} from '@tanstack/react-table'; } from '@tanstack/react-table';
import ModalProcessDelivery from './_components/modal-process-item';
type Status = 'valid' | 'invalid' | 'unchecked'; type OrderValid = 'valid' | 'invalid' | 'unchecked';
type Status = 'undelivered' | 'delivered';
interface Prize { interface Prize {
id: number; id: number;
name: string; name: string;
orderValid: Status; orderValid: OrderValid;
items: string; items: string;
address: string; address: string;
status: Status; status: Status;
@@ -46,17 +48,25 @@ const mockData: Prize[] = Array.from({ length: 90 }, (_, i) => ({
? 'invalid' ? 'invalid'
: i % 5 === 0 : i % 5 === 0
? 'unchecked' ? 'unchecked'
: 'valid') as Status, : 'valid') as OrderValid,
items: items[i % items.length], items: items[i % items.length],
address: 'Jl. Pantai Cibaduyut Indah', address: 'Jl. Pantai Cibaduyut Indah',
status: (i % 3 === 0 status: (i % 3 === 0 ? 'undelivered' : 'delivered') as Status,
? 'unchecked'
: i % 5 === 0
? 'invalid'
: 'valid') as Status,
})); }));
const columns: ColumnDef<Prize>[] = [ export const Components: FC = (): ReactElement => {
const [showModalProcessDelivery, setShowModalProcessDelivery] =
useState(false);
const [pagination, setPagination] = React.useState<PaginationState>({
pageIndex: 0,
pageSize: 9,
});
const [rowSelection, setRowSelection] = React.useState<RowSelectionState>({});
const [showFilter, setShowFilter] = useState(false);
const columns: ColumnDef<Prize>[] = [
{ {
id: 'select', id: 'select',
header: ({ table }) => ( header: ({ table }) => (
@@ -89,12 +99,12 @@ const columns: ColumnDef<Prize>[] = [
accessorKey: 'orderValid', accessorKey: 'orderValid',
cell: ({ row }) => { cell: ({ row }) => {
const status = row.original.orderValid; const status = row.original.orderValid;
const statusColors: Record<Status, string> = { const statusColors: Record<OrderValid, string> = {
valid: 'bg-success-200 text-success-500', valid: 'bg-success-200 text-success-500',
invalid: 'bg-danger-200 text-danger-500', invalid: 'bg-danger-200 text-danger-500',
unchecked: 'bg-warning-200 text-warning-900', unchecked: 'bg-warning-200 text-warning-900',
}; };
const statusText: Record<Status, string> = { const statusText: Record<OrderValid, string> = {
valid: 'Valid', valid: 'Valid',
invalid: 'Invalid', invalid: 'Invalid',
unchecked: 'Unchecked', unchecked: 'Unchecked',
@@ -122,14 +132,12 @@ const columns: ColumnDef<Prize>[] = [
cell: ({ row }) => { cell: ({ row }) => {
const status = row.original.status; const status = row.original.status;
const statusColors: Record<Status, string> = { const statusColors: Record<Status, string> = {
valid: 'bg-success-200 text-success-500', delivered: 'bg-success-200 text-success-500',
invalid: 'bg-danger-200 text-danger-500', undelivered: 'bg-danger-200 text-danger-500',
unchecked: 'bg-warning-200 text-warning-900',
}; };
const statusText: Record<Status, string> = { const statusText: Record<Status, string> = {
valid: 'Valid', delivered: 'Delivered',
invalid: 'Invalid', undelivered: 'Undelivered',
unchecked: 'Unchecked',
}; };
return ( return (
<div <div
@@ -147,8 +155,7 @@ const columns: ColumnDef<Prize>[] = [
variant="primary" variant="primary"
size="sm" size="sm"
onClick={(e) => { onClick={(e) => {
e.stopPropagation(); setShowModalProcessDelivery(true);
// handleUpdate(row.id);
}} }}
className="flex items-center gap-2 w-full" className="flex items-center gap-2 w-full"
> >
@@ -156,16 +163,7 @@ const columns: ColumnDef<Prize>[] = [
</Button> </Button>
), ),
}, },
]; ];
export const Components: FC = (): ReactElement => {
const [pagination, setPagination] = React.useState<PaginationState>({
pageIndex: 0,
pageSize: 9,
});
const [rowSelection, setRowSelection] = React.useState<RowSelectionState>({});
const [showFilter, setShowFilter] = useState(false);
const table = useReactTable({ const table = useReactTable({
data: mockData, data: mockData,
@@ -184,12 +182,12 @@ export const Components: FC = (): ReactElement => {
}); });
return ( return (
<Fragment>
<main className="w-full px-[48px] py-[40px] flex flex-col gap-8"> <main className="w-full px-[48px] py-[40px] flex flex-col gap-8">
{/* Header */} {/* Header */}
<header className="bg-white py-4 px-8 rounded-lg shadow p-4"> <header className="bg-white py-4 px-8 rounded-lg shadow p-4">
<h1 className="text-p2 font-semibold">Data Pengiriman Hadiah</h1> <h1 className="text-p2 font-semibold">Data Pengiriman Hadiah</h1>
</header> </header>
{/* Account Table Section */} {/* Account Table Section */}
<section className="flex flex-col gap-6 p-8 bg-white rounded-md"> <section className="flex flex-col gap-6 p-8 bg-white rounded-md">
{/* Search and Filter */} {/* Search and Filter */}
@@ -203,7 +201,6 @@ export const Components: FC = (): ReactElement => {
<SearchOutlined /> <SearchOutlined />
</div> </div>
</div> </div>
<div className="relative"> <div className="relative">
<Button <Button
variant="primary" variant="primary"
@@ -221,11 +218,20 @@ export const Components: FC = (): ReactElement => {
)} )}
</div> </div>
</div> </div>
{/* Table */} {/* Table */}
<DataTable data={mockData} columns={columns} table={table} /> <DataTable data={mockData} columns={columns} table={table} />
</section> </section>
</main> </main>
{/* Modal Process Delivery */}
<ModalProcessDelivery
isOpen={showModalProcessDelivery}
onClose={() => setShowModalProcessDelivery(false)}
onProcessDelivery={() => {
console.log('Item added');
}}
/>
</Fragment>
); );
}; };