diff --git a/src/api/index.ts b/src/api/index.ts index c68f4b2..a80537c 100644 --- a/src/api/index.ts +++ b/src/api/index.ts @@ -29,6 +29,9 @@ export const ApiId = { CONTRACTS: id++, + LOGIN_USERS: id++, + LOGIN_USER_CREATE: id++, + // FOR CUSTOM HT_CUSTOM_CUSTOMERS: id++, HT_CUSTOM_PARKINGS: id++, diff --git a/src/api/login-user.ts b/src/api/login-user.ts new file mode 100644 index 0000000..4b9903e --- /dev/null +++ b/src/api/login-user.ts @@ -0,0 +1,48 @@ +import { APICommonResponse, ApiId, HttpMethod, makeParam, request } from "."; +import { getUrl } from "./url"; + +export type LoginUser = { + id: string; + name: string; + email: string; + contract_id: string; + updated_at: string; +}; + +// ログインユーザー一覧取得 ----------------------- +export type LoginUsersRequest = { + id?: string; + name?: string; + email?: string; +}; + +export type LoginUsersResponse = { + data: { + records: LoginUser[]; + }; +} & APICommonResponse; + +export const getLoginUsers = async (data: LoginUsersRequest) => { + const res = await request({ + url: getUrl(ApiId.LOGIN_USERS), + method: HttpMethod.GET, + data: new URLSearchParams(data), + }); + return res; +}; + +// ログインユーザー新規作成 +export type LoginUserCreateRequest = { + name: string; + email: string; + password: string; +}; + +export const createLoginUser = async (data: LoginUserCreateRequest) => { + const res = await request({ + url: getUrl(ApiId.LOGIN_USER_CREATE), + method: HttpMethod.POST, + data: makeParam(data), + }); + return res; +}; diff --git a/src/api/url.ts b/src/api/url.ts index d3f1f57..4c1b193 100644 --- a/src/api/url.ts +++ b/src/api/url.ts @@ -19,6 +19,8 @@ const urls = { [A.RECEIPT_ISSUING_ORDERS]: "receipt-issuing-orders", [A.CONTRACTS]: "contracts", + [A.LOGIN_USERS]: "users", + [A.LOGIN_USER_CREATE]: "user/create", // FOR CUSTOM [A.HT_CUSTOM_CUSTOMERS]: "custom/hello-techno/customers", diff --git a/src/codes/page.ts b/src/codes/page.ts index e07de21..f6e1bd2 100644 --- a/src/codes/page.ts +++ b/src/codes/page.ts @@ -18,6 +18,9 @@ export const PageID = { DASHBOARD_RECEIPT_ISSUING_ORDER_LIST_CUSTOM_HELLO_TECHNO: id++, DASHBOARD_RECEIPT_ISSUING_ORDER_DETAIL_CUSTOM_HELLO_TECHNO: id++, + DASHBOARD_LOGIN_USER_LIST: id++, + DASHBOARD_LOGIN_USER_CREATE: id++, + PAGE_403: id++, PAGE_404: id++, } as const; diff --git a/src/layouts/dashbord/navigator.tsx b/src/layouts/dashbord/navigator.tsx index 0ecd36f..d45efeb 100644 --- a/src/layouts/dashbord/navigator.tsx +++ b/src/layouts/dashbord/navigator.tsx @@ -1,6 +1,7 @@ import { ExpandLess, ExpandMore } from "@mui/icons-material"; import HomeIcon from "@mui/icons-material/Home"; import PeopleIcon from "@mui/icons-material/People"; +import ArticleIcon from "@mui/icons-material/Article"; import SettingsIcon from "@mui/icons-material/Settings"; import { Collapse } from "@mui/material"; import Box from "@mui/material/Box"; @@ -57,7 +58,7 @@ const categories: Group[] = [ }, { label: "領収証発行依頼", - icon: , + icon: , children: [ { id: PageID.DASHBOARD_RECEIPT_ISSUING_ORDER_LIST_CUSTOM_HELLO_TECHNO, @@ -69,6 +70,20 @@ const categories: Group[] = [ }, ], }, + { + label: "ユーザ管理", + icon: , + children: [ + { + id: PageID.DASHBOARD_LOGIN_USER_LIST, + label: "一覧", + }, + { + id: PageID.DASHBOARD_LOGIN_USER_CREATE, + label: "作成", + }, + ], + }, ], }, { @@ -103,7 +118,7 @@ export default function Navigator(props: DrawerProps) { - SateReceipt + EasyReceipt diff --git a/src/pages/dashboard/login-user/create.tsx b/src/pages/dashboard/login-user/create.tsx new file mode 100644 index 0000000..65f0276 --- /dev/null +++ b/src/pages/dashboard/login-user/create.tsx @@ -0,0 +1,117 @@ +import { yupResolver } from "@hookform/resolvers/yup"; +import { Box, Button, Card, Stack, Typography } from "@mui/material"; +import { HasChildren } from "@types"; +import { createLoginUser } from "api/login-user"; +import { PageID, TabID } from "codes/page"; +import { FormProvider, RHFTextField } from "components/hook-form"; +import useAPICall from "hooks/useAPICall"; +import useDashboard from "hooks/useDashBoard"; +import useNavigateCustom from "hooks/useNavigateCustom"; +import useSnackbarCustom from "hooks/useSnackbarCustom"; +import { useSnackbar } from "notistack"; +import { useEffect } from "react"; +import { useForm } from "react-hook-form"; +import { getPath } from "routes/path"; +import * as Yup from "yup"; + +type AreaBoxProps = { + title: string; +} & HasChildren; +function AreaBox({ title, children }: AreaBoxProps) { + return ( + + {title} + {children} + + ); +} + +type FormProps = { + name: string; + email: string; + password: string; + password_retype: string; +}; + +export default function LoginUserCreate() { + const { setHeaderTitle, setTabs } = useDashboard( + PageID.DASHBOARD_LOGIN_USER_CREATE, + TabID.NONE + ); + + const { success, error } = useSnackbarCustom(); + const { navigateWhenChanged } = useNavigateCustom(); + + const form = useForm({ + defaultValues: { + name: "", + email: "", + password: "", + password_retype: "", + }, + resolver: yupResolver( + Yup.object().shape({ + name: Yup.string().required("必須項目です"), + email: Yup.string().required("必須項目です"), + password: Yup.string().required("必須項目です"), + password_retype: Yup.string() + .required("必須項目です") + .test("retype", "入力が一致しません", function (value) { + return this.parent.password === value; + }), + }) + ), + }); + + const { callAPI } = useAPICall({ + apiMethod: createLoginUser, + backDrop: true, + form, + onSuccess: (res, sendData) => { + success("登録しました"); + navigateWhenChanged( + getPath(PageID.DASHBOARD_LOGIN_USER_LIST, { + query: { email: sendData.email }, + }) + ); + }, + onFailed: () => { + error("失敗しました"); + }, + }); + + const handleSubmt = (data: FormProps) => { + callAPI({ ...data }); + }; + + useEffect(() => { + setHeaderTitle("ユーザ新規作成"); + setTabs(null); + }, []); + + return ( + + + + + + + + + + + + + + + + + + + + + + ); +} diff --git a/src/pages/dashboard/login-user/list.tsx b/src/pages/dashboard/login-user/list.tsx new file mode 100644 index 0000000..1bb9a88 --- /dev/null +++ b/src/pages/dashboard/login-user/list.tsx @@ -0,0 +1,309 @@ +import { + Box, + Button, + Dialog, + DialogActions, + DialogContent, + DialogTitle, + Drawer, + FormControl, + Grid, + IconButton, + Stack, + Table, + TableBody, + TableCell, + TableContainer, + TablePagination, + TableRow, + TextField, + Tooltip, + Typography, +} from "@mui/material"; +import { Dictionary } from "@types"; +import { + ReceiptIssuingOrderHTCustom, + getReceiptIssuingOrders, +} from "api/custom/hello-techno/receipt-issuing-order"; +import { PageID, TabID } from "codes/page"; +import { + FormProvider, + RHFCheckbox, + RHFSelect, + RHFTextField, +} from "components/hook-form"; +import { TableHeadCustom } from "components/table"; +import { SearchConditionContextProvider } from "contexts/SearchConditionContext"; +import useAPICall from "hooks/useAPICall"; +import useBackDrop from "hooks/useBackDrop"; +import useDashboard from "hooks/useDashBoard"; +import useNavigateCustom from "hooks/useNavigateCustom"; +import useSearchConditionContext from "hooks/useSearchConditionContext"; +import useTable, { UseTableReturn } from "hooks/useTable"; +import { useEffect, useMemo, useState } from "react"; +import { useForm } from "react-hook-form"; +import { getPath } from "routes/path"; +import AccountCircleIcon from "@mui/icons-material/AccountCircle"; +import { RHFSelectMuiliple } from "components/hook-form/RHFSelect"; +import useAuth from "hooks/useAuth"; +import RHFDatePicker from "components/hook-form/RHFDatePicker"; +import { dateParse, formatDateStr } from "utils/datetime"; +import { Clear } from "@mui/icons-material"; +import { LoginUser, getLoginUsers } from "api/login-user"; + +export default function LoginUserList() { + const { setHeaderTitle, setTabs } = useDashboard( + PageID.DASHBOARD_LOGIN_USER_LIST, + TabID.NONE + ); + + useEffect(() => { + setHeaderTitle("ユーザ一覧"); + setTabs(null); + }, []); + + return ( + + + + ); +} + +function Page() { + const table = useTable(); + + return ( + + + + + ); +} + +type FormProps = { + name: string; + email: string; +}; +type CommonProps = { + table: UseTableReturn; +}; +function SearchBox({ table }: CommonProps) { + const { + condition, + initialized, + get, + addCondition: add, + } = useSearchConditionContext(); + + const { setShowBackDrop } = useBackDrop(); + + const { name: myName } = useAuth(); + + const [openDateDialog, setOpenDateDialog] = useState(false); + + const form = useForm({ + defaultValues: { + name: "", + email: "", + }, + }); + + const { + callAPI: callGetLoginUsers, + makeSendData, + sending, + } = useAPICall({ + apiMethod: getLoginUsers, + form, + onSuccess: (res) => { + table.setRowData(res.data.records); + }, + }); + + const handleSubmit = async (data: FormProps) => { + addCondition(data); + }; + + const addCondition = (data: FormProps) => { + add({ + ...data, + }); + }; + + const handleBlur = () => { + addCondition(form.getValues()); + }; + + const fetch = async (data: Dictionary) => { + const sendData = makeSendData({ + ...data, + }); + callGetLoginUsers(sendData); + }; + + // 初期値設定 + useEffect(() => { + if (initialized) { + form.setValue("name", get("name")); + form.setValue("email", get("email")); + } + }, [initialized, condition]); + + // Fetchアクション + useEffect(() => { + if (initialized) { + fetch(condition); + } + }, [condition, initialized]); + + // バックドロップ + useEffect(() => { + setShowBackDrop(sending); + }, [sending]); + + return ( + + + + + + 名前 + + + + + + Email + + + + + + { + setOpenDateDialog(false); + }} + > + 受付時刻検索条件 + + + + From + + + +   + + + + To + + + + + + + + + + ); +} + +function TableBox({ table }: CommonProps) { + const TABLE_HEAD = [ + { id: "name", label: "名前", align: "left" }, + { id: "email", label: "Email", align: "left" }, + ]; + const { + order, + page, + sort, + rowsPerPage, + fetched, + fillteredRow, + isNotFound, + dataLength, + // + onSort, + onChangePage, + onChangeRowsPerPage, + // + setRowData, + // + ROWS_PER_PAGES, + } = table; + + return ( + <> + + + + + + {fillteredRow.map((row, index) => ( + + ))} + +
+
+ + + + + + ); +} + +type RowProps = { + data: LoginUser; +}; +function Row({ data }: RowProps) { + const { navigateWhenChanged } = useNavigateCustom(); + + const handleClick = () => { + // navigateWhenChanged( + // getPath( + // PageID.DASHBOARD_RECEIPT_ISSUING_ORDER_DETAIL_CUSTOM_HELLO_TECHNO, + // { + // query: { + // id: data.id, + // }, + // } + // ) + // ); + }; + + return ( + + {data.name} + {data.email} + + ); +} diff --git a/src/routes/auth.ts b/src/routes/auth.ts index b8436d7..e7c9248 100644 --- a/src/routes/auth.ts +++ b/src/routes/auth.ts @@ -32,6 +32,8 @@ export const AUTH = { R.NORMAL_ADMIN, [C.HELLO_TECHNO] ), + [P.DASHBOARD_LOGIN_USER_LIST]: setAuth("ge", R.CONTRACT_ADMIN), + [P.DASHBOARD_LOGIN_USER_CREATE]: setAuth("ge", R.CONTRACT_ADMIN), [P.PAGE_403]: setAuth("all"), [P.PAGE_404]: setAuth("all"), diff --git a/src/routes/index.tsx b/src/routes/index.tsx index 9d37ef4..71162c9 100644 --- a/src/routes/index.tsx +++ b/src/routes/index.tsx @@ -81,6 +81,14 @@ const DashboardRoutes = (): RouteObject => { pageId: PageID.DASHBOARD_RECEIPT_ISSUING_ORDER_DETAIL_CUSTOM_HELLO_TECHNO, element: , }, + { + pageId: PageID.DASHBOARD_LOGIN_USER_LIST, + element: , + }, + { + pageId: PageID.DASHBOARD_LOGIN_USER_CREATE, + element: , + }, ]; const children: RouteObject[] = useMemo(() => { @@ -157,6 +165,14 @@ const ReceiptIssuingOrderDetailHelloTechno = Loadable( ) ); +// ログインユーザー管理 +const LoginUserList = Loadable( + lazy(() => import("pages/dashboard/login-user/list")) +); +const LoginUserCreate = Loadable( + lazy(() => import("pages/dashboard/login-user/create")) +); + // その他 --------------------------------- const Page403 = Loadable(lazy(() => import("pages/common/Page403"))); const Page404 = Loadable(lazy(() => import("pages/common/Page404"))); diff --git a/src/routes/path.ts b/src/routes/path.ts index eb61bd4..2c267b1 100644 --- a/src/routes/path.ts +++ b/src/routes/path.ts @@ -61,6 +61,12 @@ const PATHS = { PageID.DASHBOARD_RECEIPT_ISSUING_ORDER_DETAIL_CUSTOM_HELLO_TECHNO )]: "/dashboard/receipt-issusing-order/detail/:id", + // ログインユーザ管理 + [makePathKey(PageID.DASHBOARD_LOGIN_USER_LIST)]: + "/dashboard/login-user/list/:page", + [makePathKey(PageID.DASHBOARD_LOGIN_USER_CREATE)]: + "/dashboard/login-user/create", + // その他 [makePathKey(PageID.PAGE_403)]: "403", [makePathKey(PageID.PAGE_404)]: "404",