updated docs
This commit is contained in:
@@ -0,0 +1,88 @@
|
||||
'use client';
|
||||
import React, { useState, useEffect } from "react";
|
||||
import { apiPostFetcher } from "@/lib/fetcher";
|
||||
import { ApiPaginationRequestWithQuery } from "@/validations/mutual/api/requests/validations";
|
||||
import { TableComponentProps } from "@/validations/mutual/table/type";
|
||||
import ComponentTable from "../mutual/TableCardPlain";
|
||||
import PaginationComponent from "../mutual/UpperPagination";
|
||||
import LowerPagination from "../mutual/LowerPagination";
|
||||
|
||||
const TableCardComponent: React.FC<TableComponentProps> = ({
|
||||
urls,
|
||||
schemas,
|
||||
translations,
|
||||
columns,
|
||||
initPagination,
|
||||
}) => {
|
||||
const defaultPagination = {
|
||||
page: initPagination?.page || 1,
|
||||
size: initPagination?.size || 10,
|
||||
orderFields: initPagination?.orderFields || [],
|
||||
orderTypes: initPagination?.orderTypes || [],
|
||||
query: initPagination?.query || {},
|
||||
}
|
||||
const [data, setData] = useState<any>(null);
|
||||
const [pagination, setPagination] = useState<ApiPaginationRequestWithQuery>(defaultPagination);
|
||||
const [apiPagination, setApiPagination] = useState<any>({
|
||||
onPage: 1,
|
||||
onPageCount: 10,
|
||||
totalPage: 1,
|
||||
totalCount: 1,
|
||||
next: false,
|
||||
back: false,
|
||||
});
|
||||
const handleBack = async () => {
|
||||
setPagination({ ...pagination, page: pagination.page > 1 ? pagination.page - 1 : pagination.page });
|
||||
await fetchData();
|
||||
}
|
||||
const handleNext = async () => {
|
||||
setPagination({ ...pagination, page: pagination.page < apiPagination.totalPage ? pagination.page + 1 : pagination.page });
|
||||
await fetchData();
|
||||
}
|
||||
const fetchData = async () => {
|
||||
const response = await apiPostFetcher({
|
||||
url: urls.list,
|
||||
isNoCache: true,
|
||||
body: {
|
||||
page: pagination.page,
|
||||
size: pagination.size,
|
||||
orderFields: pagination.orderFields,
|
||||
orderTypes: pagination.orderTypes,
|
||||
query: pagination.query,
|
||||
},
|
||||
});
|
||||
if (response && response.data) {
|
||||
setData(response.data.data);
|
||||
if (response.data.pagination) {
|
||||
setApiPagination(response.data.pagination);
|
||||
}
|
||||
}
|
||||
};
|
||||
useEffect(() => { fetchData() }, [pagination.page, pagination.size, pagination.orderFields, pagination.orderTypes]);
|
||||
const upperPaginationProps = {
|
||||
apiPagination,
|
||||
pagination,
|
||||
setPagination,
|
||||
defaultPagination,
|
||||
}
|
||||
const lowerPaginationProps = {
|
||||
pagination: apiPagination,
|
||||
handleBack,
|
||||
handleNext,
|
||||
}
|
||||
const tableProps = {
|
||||
data,
|
||||
columns,
|
||||
translations,
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className="flex flex-col items-center justify-start my-6"><PaginationComponent {...upperPaginationProps} /></div>
|
||||
<div className="flex flex-col items-center justify-start my-6"><LowerPagination {...lowerPaginationProps} /></div>
|
||||
<div className="flex flex-col items-center justify-start my-6"><h1>Post Data Page</h1><ComponentTable {...tableProps} /></div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default TableCardComponent;
|
||||
@@ -0,0 +1,104 @@
|
||||
'use client';
|
||||
import React, { useState, useEffect } from "react";
|
||||
import ComponentTable from "@/components/mutual/tableView/mutual/TablePlain";
|
||||
import PaginationComponent from "@/components/mutual/tableView/mutual/UpperPagination";
|
||||
import LowerPagination from "@/components/mutual/tableView/mutual/LowerPagination";
|
||||
import { apiPostFetcher } from "@/lib/fetcher";
|
||||
import { ApiPaginationRequestWithQuery } from "@/validations/mutual/api/requests/validations";
|
||||
import { TableComponentProps } from "@/validations/mutual/table/type";
|
||||
|
||||
const TableComponent: React.FC<TableComponentProps> = ({
|
||||
urls,
|
||||
schemas,
|
||||
translations,
|
||||
columns,
|
||||
initPagination,
|
||||
redirectUrls,
|
||||
setSelectedRow,
|
||||
}) => {
|
||||
const defaultPagination = {
|
||||
page: initPagination?.page || 1,
|
||||
size: initPagination?.size || 10,
|
||||
orderFields: initPagination?.orderFields || [],
|
||||
orderTypes: initPagination?.orderTypes || [],
|
||||
query: initPagination?.query || {},
|
||||
}
|
||||
const [tableData, setTableData] = useState<any>(null);
|
||||
const [orgTableData, setOrgTableData] = useState<any>(null);
|
||||
const [tableColumns, setTableColumns] = useState<string[]>([]);
|
||||
const [pagination, setPagination] = useState<ApiPaginationRequestWithQuery>(defaultPagination);
|
||||
const [apiPagination, setApiPagination] = useState<any>({
|
||||
onPage: 1,
|
||||
onPageCount: 10,
|
||||
totalPage: 1,
|
||||
totalCount: 1,
|
||||
next: false,
|
||||
back: false,
|
||||
});
|
||||
|
||||
const handleBack = async () => {
|
||||
setPagination({ ...pagination, page: pagination.page > 1 ? pagination.page - 1 : pagination.page });
|
||||
await fetchData();
|
||||
}
|
||||
const handleNext = async () => {
|
||||
setPagination({ ...pagination, page: pagination.page < apiPagination.totalPage ? pagination.page + 1 : pagination.page });
|
||||
await fetchData();
|
||||
}
|
||||
const fetchData = async () => {
|
||||
const response = await apiPostFetcher({
|
||||
url: urls.list,
|
||||
isNoCache: true,
|
||||
body: {
|
||||
page: pagination.page,
|
||||
size: pagination.size,
|
||||
orderFields: pagination.orderFields,
|
||||
orderTypes: pagination.orderTypes,
|
||||
query: pagination.query,
|
||||
},
|
||||
});
|
||||
if (response && response.data) {
|
||||
const oldData = response.data.data
|
||||
setOrgTableData(oldData)
|
||||
if (schemas.table) {
|
||||
const newData = Object.entries(oldData).map(([key]) => {
|
||||
return schemas.table.safeParse(oldData[key as keyof typeof oldData]).data
|
||||
})
|
||||
setTableData(newData)
|
||||
setTableColumns(columns.table)
|
||||
}
|
||||
if (response.data.pagination) {
|
||||
setApiPagination(response.data.pagination);
|
||||
}
|
||||
}
|
||||
};
|
||||
useEffect(() => { fetchData() }, [pagination.page, pagination.size, pagination.orderFields, pagination.orderTypes]);
|
||||
|
||||
const upperPaginationProps = {
|
||||
apiPagination,
|
||||
pagination,
|
||||
setPagination,
|
||||
defaultPagination,
|
||||
}
|
||||
const lowerPaginationProps = {
|
||||
pagination: apiPagination,
|
||||
handleBack,
|
||||
handleNext,
|
||||
}
|
||||
const tableProps = {
|
||||
data: tableData,
|
||||
orgData: orgTableData,
|
||||
columns: tableColumns,
|
||||
translations,
|
||||
redirectUrls,
|
||||
setSelectedRow,
|
||||
}
|
||||
return (
|
||||
<div>
|
||||
<div className="flex flex-col items-center justify-start my-6"><PaginationComponent {...upperPaginationProps} /></div>
|
||||
<div className="flex flex-col items-center justify-start my-6"><LowerPagination {...lowerPaginationProps} /></div>
|
||||
<div className="flex flex-col items-center justify-start my-6"><ComponentTable {...tableProps} /></div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default TableComponent;
|
||||
@@ -0,0 +1,40 @@
|
||||
import React from "react";
|
||||
import { CreateFormProps } from "@/validations/mutual/forms/type";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { Form } from "@/components/mutual/shadcnui/form";
|
||||
import { renderInputsBySchema } from "@/lib/renderInputs";
|
||||
import { Button } from "@/components/mutual/shadcnui/button";
|
||||
|
||||
const CreateForm: React.FC<CreateFormProps> = ({ schemas, labels, selectedRow }) => {
|
||||
const createSchema = schemas.create
|
||||
const findLabels = Object.entries(createSchema?.shape || {}).reduce((acc: any, [key, value]: any) => {
|
||||
acc[key] = {
|
||||
label: labels[key] || key,
|
||||
description: value.description,
|
||||
}
|
||||
return acc
|
||||
}, {})
|
||||
const handleSubmit = (data: any) => {
|
||||
console.log(data)
|
||||
}
|
||||
const form = useForm<FormData>({
|
||||
resolver: zodResolver(createSchema),
|
||||
defaultValues: {},
|
||||
});
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div>Create Form</div>
|
||||
<Form {...form}>
|
||||
<form onSubmit={form.handleSubmit(handleSubmit)} className="space-y-4">
|
||||
{renderInputsBySchema(findLabels, form)}
|
||||
<Button type="submit">Submit</Button>
|
||||
</form>
|
||||
</Form>
|
||||
<div>selectedRow: {JSON.stringify(selectedRow)}</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default CreateForm
|
||||
@@ -0,0 +1,24 @@
|
||||
'use client'
|
||||
import { Button } from "@/components/mutual/shadcnui/button";
|
||||
import { LowerPaginationProps } from "@/validations/mutual/pagination/type";
|
||||
|
||||
const LowerPagination: React.FC<LowerPaginationProps> = ({
|
||||
pagination,
|
||||
handleBack,
|
||||
handleNext,
|
||||
}) => {
|
||||
const paginationBackComponent = pagination.back ? (
|
||||
<Button className="w-60" onClick={() => handleBack()}>Back</Button>
|
||||
) : <></>;
|
||||
const paginationNextComponent = pagination.next ? (
|
||||
<Button className="w-60" onClick={() => handleNext()}>Next</Button>
|
||||
) : <></>;
|
||||
return (
|
||||
<div className="flex items-center justify-center gap-2 bg-amber-300 p-6 w-full">
|
||||
{paginationBackComponent}
|
||||
{paginationNextComponent}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default LowerPagination
|
||||
@@ -0,0 +1,34 @@
|
||||
import { Input } from "@/components/mutual/shadcnui/input";
|
||||
import { Label } from "@/components/mutual/shadcnui/label";
|
||||
import { PaginationDetailsProps } from "@/validations/mutual/pagination/type";
|
||||
|
||||
const PaginationDetails: React.FC<PaginationDetailsProps> = ({
|
||||
pagination,
|
||||
setPagination,
|
||||
defaultPagination,
|
||||
}) => {
|
||||
return (
|
||||
<div className="grid grid-cols-6 gap-2 items-center justify-evenly">
|
||||
<Label>Page Size</Label>
|
||||
<Input
|
||||
type="number"
|
||||
value={pagination.size}
|
||||
onChange={(e) => setPagination({ ...defaultPagination, size: Number(e.target.value) })}
|
||||
/>
|
||||
<Label>Order Field</Label>
|
||||
<Input
|
||||
type="text"
|
||||
value={pagination.orderFields.join(",")}
|
||||
onChange={(e) => setPagination({ ...defaultPagination, orderFields: e.target.value.split(",") })}
|
||||
/>
|
||||
<Label>Order Type</Label>
|
||||
<Input
|
||||
type="text"
|
||||
value={pagination.orderTypes.join(",")}
|
||||
onChange={(e) => setPagination({ ...pagination, orderType: e.target.value.split(",") })}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default PaginationDetails
|
||||
@@ -0,0 +1,15 @@
|
||||
import { PaginationShowProps } from "@/validations/mutual/pagination/type"
|
||||
|
||||
const PaginationShow: React.FC<PaginationShowProps> = ({ apiPagination }) => {
|
||||
return (
|
||||
<div className="grid grid-cols-6 gap-2 items-center justify-evenly">
|
||||
<p>Page: {apiPagination.onPage}</p>
|
||||
<p>Page Count: {apiPagination.onPageCount}</p>
|
||||
<p>Total Page: {apiPagination.totalPage}</p>
|
||||
<p>Total Count: {apiPagination.totalCount}</p>
|
||||
<p>Next: {apiPagination.next ? "true" : "false"}</p>
|
||||
<p>Back: {apiPagination.back ? "true" : "false"}</p>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
export default PaginationShow
|
||||
@@ -0,0 +1,24 @@
|
||||
import { Label } from "@/components/mutual/shadcnui/label";
|
||||
import { Textarea } from "@/components/mutual/shadcnui/textarea";
|
||||
import { SearchProps } from "@/validations/mutual/table/type";
|
||||
|
||||
const SearchBarComponent: React.FC<SearchProps> = ({ pagination, setPagination }) => {
|
||||
const handleSearch = (query: string) => {
|
||||
setTimeout(() => {
|
||||
setPagination({ ...pagination, query: {} })
|
||||
}, 2000)
|
||||
}
|
||||
return (
|
||||
<div>
|
||||
<div className="grid grid-cols-1 w-full px-10 py-2">
|
||||
<Label>Search</Label>
|
||||
<Textarea
|
||||
value={JSON.stringify(pagination.query, null, 2)}
|
||||
onChange={(e) => handleSearch(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default SearchBarComponent
|
||||
@@ -0,0 +1,47 @@
|
||||
'use client'
|
||||
import { Card, CardHeader, CardContent, CardTitle, CardDescription } from "@/components/mutual/shadcnui/card";
|
||||
import { TableCardProps } from "@/validations/mutual/table/type";
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
const ComponentTableCardPlain: React.FC<TableCardProps> = ({ data, columns, translations }) => {
|
||||
const [tableData, setTableData] = useState<any>(data);
|
||||
useEffect(() => {
|
||||
setTableData(data);
|
||||
}, [data]);
|
||||
|
||||
|
||||
const renderCards = () => {
|
||||
return tableData?.map((item: any, index: number) => (
|
||||
<Card className="w-full min-w-full my-2 p-5" key={index}>
|
||||
<CardHeader>
|
||||
<CardTitle>Row : {index + 1}</CardTitle>
|
||||
<CardDescription>{item.uuid}</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="flex flex-col items-start justify-start">Email: {item.email}</div>
|
||||
<div className="flex flex-col items-start justify-start">Phone Number: {item.phoneNumber}</div>
|
||||
<div>Created At: {item.createdAt}</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
))
|
||||
}
|
||||
|
||||
const noDataFound = () => (
|
||||
<>
|
||||
No Data Found
|
||||
</>
|
||||
)
|
||||
return (
|
||||
<>
|
||||
{
|
||||
tableData ? (
|
||||
<div className="w-full min-w-full">
|
||||
<div className="flex flex-col items-center justify-start my-6">{renderCards()}</div>
|
||||
</div>
|
||||
) : (noDataFound())
|
||||
}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default ComponentTableCardPlain
|
||||
@@ -0,0 +1,60 @@
|
||||
'use client'
|
||||
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/mutual/shadcnui/table";
|
||||
import { useEffect, useState } from "react";
|
||||
import { TableProps } from "@/validations/mutual/table/type";
|
||||
|
||||
const ComponentTablePlain: React.FC<TableProps> = ({
|
||||
data, orgData, columns, translations, redirectUrls, setSelectedRow
|
||||
}) => {
|
||||
const [tableData, setTableData] = useState<any>(data);
|
||||
useEffect(() => {
|
||||
setTableData(data);
|
||||
}, [data]);
|
||||
|
||||
const renderColumns = () => {
|
||||
return [translations?.rows, ...columns].map((column, index) => {
|
||||
return (
|
||||
<TableHead key={`headers-${index}`}>{column}</TableHead>
|
||||
)
|
||||
})
|
||||
}
|
||||
const renderRows = () => (
|
||||
<>{tableData?.map((item: any, index: number) => {
|
||||
return (
|
||||
<TableRow key={`${index}-row`} >
|
||||
<TableCell>{index + 1}</TableCell>
|
||||
{
|
||||
Object.entries(item).map(([key, value]: [string, any]) => (
|
||||
<TableCell key={`${index}-column-${key}`}>{value}</TableCell>
|
||||
))
|
||||
}
|
||||
|
||||
{
|
||||
Object.values(redirectUrls?.table || {}).map((redirectUrl: any, index: number) => {
|
||||
return (
|
||||
<TableCell className="cursor-pointer w-4" key={`${index}-action-${index}`}
|
||||
onClick={() => setSelectedRow?.(orgData[index])}>{redirectUrl}</TableCell>
|
||||
)
|
||||
})
|
||||
}
|
||||
</TableRow>
|
||||
)
|
||||
})}</>
|
||||
)
|
||||
const noDataFound = (<>No Data Found</>)
|
||||
const renderTable = (
|
||||
<Table><TableHeader><TableRow>{renderColumns()}</TableRow></TableHeader><TableBody>{renderRows()}</TableBody></Table>
|
||||
)
|
||||
return (
|
||||
<>
|
||||
<div className="flex flex-row justify-between gap-2">
|
||||
{Object.values(redirectUrls?.page || {}).map((action, index) => (
|
||||
<div className="flex flex-row justify-center items-center gap-2" key={`page-action-${index}`}>{action}</div>
|
||||
))}
|
||||
</div>
|
||||
{tableData ? renderTable : noDataFound}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default ComponentTablePlain
|
||||
@@ -0,0 +1,46 @@
|
||||
'use client'
|
||||
import React, { useEffect } from "react";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { UpdateFormProps } from "@/validations/mutual/forms/type";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { Form } from "@/components/mutual/shadcnui/form";
|
||||
import { renderInputsBySchema } from "@/lib/renderInputs";
|
||||
import { Button } from "@/components/mutual/shadcnui/button";
|
||||
|
||||
const UpdateForm: React.FC<UpdateFormProps> = ({ schemas, selectedRow, rollbackTo, labels }) => {
|
||||
const router = useRouter()
|
||||
useEffect(() => {
|
||||
if (!selectedRow) {
|
||||
router.push(rollbackTo, { scroll: false })
|
||||
}
|
||||
}, [selectedRow])
|
||||
const updateSchema = schemas.update
|
||||
const findLabels = Object.entries(updateSchema?.shape || {}).reduce((acc: any, [key, value]: any) => {
|
||||
acc[key] = {
|
||||
label: labels[key] || key,
|
||||
description: value.description,
|
||||
}
|
||||
return acc
|
||||
}, {})
|
||||
const handleSubmit = (data: any) => {
|
||||
console.log(data)
|
||||
}
|
||||
const form = useForm<FormData>({
|
||||
resolver: zodResolver(updateSchema),
|
||||
defaultValues: selectedRow,
|
||||
});
|
||||
return (
|
||||
<div>
|
||||
<div>Update Form</div>
|
||||
<Form {...form}>
|
||||
<form onSubmit={form.handleSubmit(handleSubmit)} className="space-y-4">
|
||||
{selectedRow && renderInputsBySchema(findLabels, form)}
|
||||
{selectedRow && <Button type="submit">Submit</Button>}
|
||||
</form>
|
||||
</Form>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default UpdateForm
|
||||
@@ -0,0 +1,21 @@
|
||||
import { PaginationProps } from "@/validations/mutual/pagination/type";
|
||||
import PaginationDetails from "./PaginationDetails";
|
||||
import PaginationShow from "./PaginationShow";
|
||||
import SearchBarComponent from "./Search";
|
||||
|
||||
const PaginationComponent: React.FC<PaginationProps> = ({
|
||||
apiPagination,
|
||||
pagination,
|
||||
setPagination,
|
||||
defaultPagination,
|
||||
}) => {
|
||||
return (
|
||||
<>
|
||||
<PaginationDetails pagination={pagination} setPagination={setPagination} defaultPagination={defaultPagination} />
|
||||
<SearchBarComponent pagination={pagination} setPagination={setPagination} />
|
||||
<PaginationShow apiPagination={apiPagination} />
|
||||
</ >
|
||||
)
|
||||
}
|
||||
|
||||
export default PaginationComponent
|
||||
@@ -0,0 +1,30 @@
|
||||
'use client'
|
||||
import React, { useEffect } from "react";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { ViewFormProps } from "@/validations/mutual/forms/type";
|
||||
import { renderInputsBySchemaView } from "@/lib/renderInputs";
|
||||
|
||||
const ViewForm: React.FC<ViewFormProps> = ({ schemas, selectedRow, rollbackTo, labels }) => {
|
||||
const router = useRouter()
|
||||
useEffect(() => {
|
||||
if (!selectedRow) {
|
||||
router.push(rollbackTo, { scroll: false })
|
||||
}
|
||||
}, [selectedRow])
|
||||
const viewSchema = schemas.view
|
||||
const findLabels = Object.entries(viewSchema?.shape || {}).reduce((acc: any, [key, value]: any) => {
|
||||
acc[key] = {
|
||||
label: labels[key] || key,
|
||||
description: value.description,
|
||||
}
|
||||
return acc
|
||||
}, {})
|
||||
return (
|
||||
<div>
|
||||
<div>View Form</div>
|
||||
{selectedRow && renderInputsBySchemaView(findLabels, selectedRow)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default ViewForm
|
||||
Reference in New Issue
Block a user