| @@ -5,6 +5,7 @@ export type Contract = { | |||||
| id: string; | id: string; | ||||
| name: string; | name: string; | ||||
| custom?: string; | custom?: string; | ||||
| contract_code?: string; | |||||
| updated_at: string; | updated_at: string; | ||||
| }; | }; | ||||
| @@ -20,6 +20,7 @@ import useDashboard from "hooks/useDashBoard"; | |||||
| import useSnackbarCustom from "hooks/useSnackbarCustom"; | import useSnackbarCustom from "hooks/useSnackbarCustom"; | ||||
| import { useEffect, useMemo, useState } from "react"; | import { useEffect, useMemo, useState } from "react"; | ||||
| import { useForm } from "react-hook-form"; | import { useForm } from "react-hook-form"; | ||||
| import useInput from "./hooks/useInput"; | |||||
| type AreaBoxProps = { | type AreaBoxProps = { | ||||
| title: string; | title: string; | ||||
| @@ -56,18 +57,22 @@ export default function ContractCreate() { | |||||
| return 0; | return 0; | ||||
| }, [mode]); | }, [mode]); | ||||
| const form = useForm<FormProps>({ | |||||
| defaultValues: { | |||||
| name: "", | |||||
| custom: "", | |||||
| contract_code: "", | |||||
| const input = useInput({ | |||||
| onSubmit: () => { | |||||
| setMode("confirm"); | |||||
| }, | }, | ||||
| }); | }); | ||||
| const handleSubmit = () => { | |||||
| callAPI({ | |||||
| ...input.form.getValues(), | |||||
| }); | |||||
| }; | |||||
| const { callAPI } = useAPICall({ | const { callAPI } = useAPICall({ | ||||
| apiMethod: createContract, | apiMethod: createContract, | ||||
| backDrop: true, | backDrop: true, | ||||
| form, | |||||
| form: input.form, | |||||
| onSuccess: () => { | onSuccess: () => { | ||||
| success("登録しました"); | success("登録しました"); | ||||
| setMode("done"); | setMode("done"); | ||||
| @@ -78,12 +83,6 @@ export default function ContractCreate() { | |||||
| }, | }, | ||||
| }); | }); | ||||
| const handleSubmit = () => { | |||||
| callAPI({ | |||||
| ...form.getValues(), | |||||
| }); | |||||
| }; | |||||
| useEffect(() => { | useEffect(() => { | ||||
| setHeaderTitle("契約者作成"); | setHeaderTitle("契約者作成"); | ||||
| setTabs(null); | setTabs(null); | ||||
| @@ -101,33 +100,7 @@ export default function ContractCreate() { | |||||
| <StepLabel>完了</StepLabel> | <StepLabel>完了</StepLabel> | ||||
| </Step> | </Step> | ||||
| </Stepper> | </Stepper> | ||||
| {mode === "input" && ( | |||||
| <> | |||||
| <FormProvider | |||||
| methods={form} | |||||
| onSubmit={form.handleSubmit(() => { | |||||
| setMode("confirm"); | |||||
| })} | |||||
| > | |||||
| <Stack spacing={2} sx={{ p: 1, m: 1 }}> | |||||
| <AreaBox title="契約者名"> | |||||
| <RHFTextField name="name" size="small" /> | |||||
| </AreaBox> | |||||
| <AreaBox title="契約識別子"> | |||||
| <RHFTextField name="contract_code" size="small" /> | |||||
| </AreaBox> | |||||
| <AreaBox title="カスタム識別子"> | |||||
| <RHFTextField name="custom" size="small" /> | |||||
| </AreaBox> | |||||
| <Stack direction="row" spacing={2}> | |||||
| <Button variant="contained" type="submit"> | |||||
| 次へ | |||||
| </Button> | |||||
| </Stack> | |||||
| </Stack> | |||||
| </FormProvider> | |||||
| </> | |||||
| )} | |||||
| {mode === "input" && input.element} | |||||
| {mode === "confirm" && ( | {mode === "confirm" && ( | ||||
| <> | <> | ||||
| <Stack spacing={2} sx={{ p: 1, py: 3, m: 1, maxWidth: 500 }}> | <Stack spacing={2} sx={{ p: 1, py: 3, m: 1, maxWidth: 500 }}> | ||||
| @@ -136,15 +109,15 @@ export default function ContractCreate() { | |||||
| <TableBody> | <TableBody> | ||||
| <TableRow> | <TableRow> | ||||
| <TableCell>契約者名</TableCell> | <TableCell>契約者名</TableCell> | ||||
| <TableCell>{form.getValues("name")}</TableCell> | |||||
| <TableCell>{input.form.getValues("name")}</TableCell> | |||||
| </TableRow> | </TableRow> | ||||
| <TableRow> | <TableRow> | ||||
| <TableCell>契約識別子</TableCell> | <TableCell>契約識別子</TableCell> | ||||
| <TableCell>{form.getValues("contract_code")}</TableCell> | |||||
| <TableCell>{input.form.getValues("contract_code")}</TableCell> | |||||
| </TableRow> | </TableRow> | ||||
| <TableRow> | <TableRow> | ||||
| <TableCell>カスタム識別子</TableCell> | <TableCell>カスタム識別子</TableCell> | ||||
| <TableCell>{form.getValues("custom")}</TableCell> | |||||
| <TableCell>{input.form.getValues("custom")}</TableCell> | |||||
| </TableRow> | </TableRow> | ||||
| </TableBody> | </TableBody> | ||||
| </Table> | </Table> | ||||
| @@ -1,7 +1,13 @@ | |||||
| import { Box } from "@mui/material"; | |||||
| import { Box, Card, Stack, formControlClasses } from "@mui/material"; | |||||
| import { PageID, TabID } from "codes/page"; | import { PageID, TabID } from "codes/page"; | ||||
| import useDashboard from "hooks/useDashBoard"; | import useDashboard from "hooks/useDashBoard"; | ||||
| import { useEffect } from "react"; | |||||
| import { useEffect, useState } from "react"; | |||||
| import useInput from "./hooks/useInput"; | |||||
| import { Contract, getContracts } from "api/contract"; | |||||
| import useAPICall from "hooks/useAPICall"; | |||||
| import useSnackbarCustom from "hooks/useSnackbarCustom"; | |||||
| import useNavigateCustom from "hooks/useNavigateCustom"; | |||||
| import { useParams } from "react-router-dom"; | |||||
| export default function ContractDetail() { | export default function ContractDetail() { | ||||
| const { setHeaderTitle, setTabs } = useDashboard( | const { setHeaderTitle, setTabs } = useDashboard( | ||||
| @@ -9,9 +15,61 @@ export default function ContractDetail() { | |||||
| TabID.NONE | TabID.NONE | ||||
| ); | ); | ||||
| const { id: paramId } = useParams(); | |||||
| const { success, error, warn } = useSnackbarCustom(); | |||||
| const { navigate } = useNavigateCustom(); | |||||
| const [contract, setContract] = useState<Contract | null>(null); | |||||
| const { callAPI: callGetContracts } = useAPICall({ | |||||
| apiMethod: getContracts, | |||||
| backDrop: true, | |||||
| onSuccess: ({ data }) => { | |||||
| if (data.records.length !== 1) { | |||||
| error("データ取得失敗"); | |||||
| navigate(-1); | |||||
| return; | |||||
| } | |||||
| setContract(data.records[0]); | |||||
| }, | |||||
| onFailed: () => { | |||||
| error("データ取得失敗"); | |||||
| navigate(-1); | |||||
| }, | |||||
| }); | |||||
| const input = useInput({ | |||||
| onSubmit: () => { | |||||
| warn("未実装"); | |||||
| }, | |||||
| nextButtonText: "更新", | |||||
| }); | |||||
| const fetch = () => { | |||||
| if (!paramId) return; | |||||
| callGetContracts({ | |||||
| id: paramId, | |||||
| }); | |||||
| }; | |||||
| useEffect(() => { | useEffect(() => { | ||||
| setHeaderTitle("契約者詳細"); | setHeaderTitle("契約者詳細"); | ||||
| setTabs(null); | setTabs(null); | ||||
| fetch(); | |||||
| }, []); | }, []); | ||||
| return <Box>ContractDetail</Box>; | |||||
| useEffect(() => { | |||||
| if (contract) { | |||||
| input.setValues(contract); | |||||
| } | |||||
| }, [contract]); | |||||
| return ( | |||||
| <Box> | |||||
| <Stack> | |||||
| <Card>{input.element}</Card> | |||||
| </Stack> | |||||
| </Box> | |||||
| ); | |||||
| } | } | ||||
| @@ -0,0 +1,70 @@ | |||||
| import { Box, Button, Stack, Typography } from "@mui/material"; | |||||
| import { HasChildren } from "@types"; | |||||
| import { Contract } from "api/contract"; | |||||
| import { FormProvider, RHFTextField } from "components/hook-form"; | |||||
| import { useForm } from "react-hook-form"; | |||||
| type AreaBoxProps = { | |||||
| title: string; | |||||
| } & HasChildren; | |||||
| function AreaBox({ title, children }: AreaBoxProps) { | |||||
| return ( | |||||
| <Box sx={{ maxWidth: 500 }}> | |||||
| <Typography variant="subtitle1">{title}</Typography> | |||||
| {children} | |||||
| </Box> | |||||
| ); | |||||
| } | |||||
| type FormProps = { | |||||
| name: string; | |||||
| custom: string; | |||||
| contract_code: string; | |||||
| }; | |||||
| type Props = { | |||||
| onSubmit: (data: FormProps) => void; | |||||
| nextButtonText?: string; | |||||
| }; | |||||
| export default function useInput({ onSubmit, nextButtonText }: Props) { | |||||
| const form = useForm<FormProps>({ | |||||
| defaultValues: { | |||||
| name: "", | |||||
| custom: "", | |||||
| contract_code: "", | |||||
| }, | |||||
| }); | |||||
| const setValues = (contract: Contract) => { | |||||
| form.setValue("name", contract.name); | |||||
| form.setValue("contract_code", contract.contract_code ?? ""); | |||||
| form.setValue("custom", contract.custom ?? ""); | |||||
| }; | |||||
| const element = ( | |||||
| <FormProvider methods={form} onSubmit={form.handleSubmit(onSubmit)}> | |||||
| <Stack spacing={2} sx={{ p: 1, m: 1 }}> | |||||
| <AreaBox title="契約者名"> | |||||
| <RHFTextField name="name" size="small" /> | |||||
| </AreaBox> | |||||
| <AreaBox title="契約識別子"> | |||||
| <RHFTextField name="contract_code" size="small" /> | |||||
| </AreaBox> | |||||
| <AreaBox title="カスタム識別子"> | |||||
| <RHFTextField name="custom" size="small" /> | |||||
| </AreaBox> | |||||
| <Stack direction="row" spacing={2}> | |||||
| <Button variant="contained" type="submit"> | |||||
| {nextButtonText ?? "次へ"} | |||||
| </Button> | |||||
| </Stack> | |||||
| </Stack> | |||||
| </FormProvider> | |||||
| ); | |||||
| return { | |||||
| element, | |||||
| form, | |||||
| setValues, | |||||
| }; | |||||
| } | |||||
| @@ -1,5 +1,6 @@ | |||||
| import { | import { | ||||
| Box, | Box, | ||||
| Button, | |||||
| Grid, | Grid, | ||||
| Stack, | Stack, | ||||
| Table, | Table, | ||||
| @@ -14,6 +15,7 @@ import { Dictionary } from "@types"; | |||||
| import { Contract, getContracts } from "api/contract"; | import { Contract, getContracts } from "api/contract"; | ||||
| import { PageID, TabID } from "codes/page"; | import { PageID, TabID } from "codes/page"; | ||||
| import { FormProvider, RHFTextField } from "components/hook-form"; | import { FormProvider, RHFTextField } from "components/hook-form"; | ||||
| import StackRow from "components/stack/StackRow"; | |||||
| import { TableHeadCustom } from "components/table"; | import { TableHeadCustom } from "components/table"; | ||||
| import { HeadLabelProps } from "components/table/TableHeadCustom"; | import { HeadLabelProps } from "components/table/TableHeadCustom"; | ||||
| import { SearchConditionContextProvider } from "contexts/SearchConditionContext"; | import { SearchConditionContextProvider } from "contexts/SearchConditionContext"; | ||||
| @@ -158,6 +160,7 @@ function TableBox({ table }: CommonProps) { | |||||
| const TABLE_HEAD: HeadLabelProps[] = [ | const TABLE_HEAD: HeadLabelProps[] = [ | ||||
| { id: "name", label: "名前", align: "left" }, | { id: "name", label: "名前", align: "left" }, | ||||
| { id: "custom", label: "カスタム", align: "left" }, | { id: "custom", label: "カスタム", align: "left" }, | ||||
| { id: "-", label: "アクション", align: "left", needSort: false }, | |||||
| ]; | ]; | ||||
| const { | const { | ||||
| order, | order, | ||||
| @@ -226,7 +229,18 @@ function Row({ data }: RowProps) { | |||||
| const { navigateWhenChanged } = useNavigateCustom(); | const { navigateWhenChanged } = useNavigateCustom(); | ||||
| const { changeContractId } = useAuth(); | const { changeContractId } = useAuth(); | ||||
| const { info } = useSnackbarCustom(); | const { info } = useSnackbarCustom(); | ||||
| const handleClick = () => { | |||||
| const handleClickEdit = () => { | |||||
| navigateWhenChanged( | |||||
| getPath(PageID.DASHBOARD_CONTRACT_DETAIL, { | |||||
| query: { | |||||
| id: data.id, | |||||
| }, | |||||
| }) | |||||
| ); | |||||
| }; | |||||
| const handleClickChangeContract = () => { | |||||
| changeContractId(data.id).then((res) => { | changeContractId(data.id).then((res) => { | ||||
| info("成り代わりました"); | info("成り代わりました"); | ||||
| navigateWhenChanged(getPath(PageID.DASHBOARD_OVERVIEW)); | navigateWhenChanged(getPath(PageID.DASHBOARD_OVERVIEW)); | ||||
| @@ -234,9 +248,17 @@ function Row({ data }: RowProps) { | |||||
| }; | }; | ||||
| return ( | return ( | ||||
| <TableRow hover sx={{ cursor: "pointer" }} onClick={handleClick}> | |||||
| <TableRow> | |||||
| <TableCell>{data.name}</TableCell> | <TableCell>{data.name}</TableCell> | ||||
| <TableCell>{data.custom ?? "-"}</TableCell> | <TableCell>{data.custom ?? "-"}</TableCell> | ||||
| <TableCell> | |||||
| <StackRow> | |||||
| <Button variant="contained" onClick={handleClickEdit}> | |||||
| 編集 | |||||
| </Button> | |||||
| <Button onClick={handleClickChangeContract}>成り代わり</Button> | |||||
| </StackRow> | |||||
| </TableCell> | |||||
| </TableRow> | </TableRow> | ||||
| ); | ); | ||||
| } | } | ||||
| @@ -1,5 +0,0 @@ | |||||
| import { Data } from "./common"; | |||||
| export type Contract = { | |||||
| name: string; | |||||
| } & Data; | |||||