Procházet zdrojové kódy

成り代わり機能 追加

develop
sosuke.iwabuchi před 2 roky
rodič
revize
c5601247ba
11 změnil soubory, kde provedl 155 přidání a 32 odebrání
  1. +12
    -2
      src/api/auth.ts
  2. +2
    -0
      src/api/index.ts
  3. +1
    -0
      src/api/url.ts
  4. +1
    -0
      src/codes/page.ts
  5. +41
    -9
      src/contexts/AuthContext.tsx
  6. +26
    -6
      src/layouts/dashbord/navigator.tsx
  7. +26
    -0
      src/pages/auth/clear-contract.tsx
  8. +12
    -3
      src/pages/dashboard/contract/list.tsx
  9. +28
    -12
      src/routes/auth.ts
  10. +5
    -0
      src/routes/index.tsx
  11. +1
    -0
      src/routes/path.ts

+ 12
- 2
src/api/auth.ts Zobrazit soubor

@@ -1,12 +1,12 @@
import { UserRole } from "codes/user";
import { APICommonResponse, ApiId, HttpMethod, request } from ".";
import { APICommonResponse, ApiId, HttpMethod, makeParam, request } from ".";
import { getUrl } from "./url";
import { CustomCode } from "codes/custom";

type MeResponse = {
data: {
id: string;
contract_id: string;
contract_id: string | null;
role: UserRole;
name: string;
custom?: CustomCode[];
@@ -45,3 +45,13 @@ export const logout = async () => {
});
return res;
};

// 成り代わり
export const changeContract = async (param: { contract_id: string | null }) => {
const res = await request<MeResponse>({
url: getUrl(ApiId.CHANGE_CONTRACT),
method: HttpMethod.POST,
data: makeParam(param),
});
return res;
};

+ 2
- 0
src/api/index.ts Zobrazit soubor

@@ -21,6 +21,8 @@ export const ApiId = {
RECEIPT_ISSUING_ORDER_MAIL_ORDER: id++,

// DASHBOARD向け-------------------------------
CHANGE_CONTRACT: id++,

RECEIPT_ISSUING_ORDERS: id++,
RECEIPT_ISSUING_ORDER: id++,
RECEIPT_ISSUING_ORDER_CREATE: id++,


+ 1
- 0
src/api/url.ts Zobrazit soubor

@@ -7,6 +7,7 @@ const urls = {
[A.ME]: "me",
[A.LOGIN]: "login",
[A.LOGOUT]: "logout",
[A.CHANGE_CONTRACT]: "change-contract",

[A.APP_TOKEN_CHECK]: "app-token-check",
[A.RECEIPT_ISSUING_ORDER_CONFIRM]: "receipt-issuing-order/confirm",


+ 1
- 0
src/codes/page.ts Zobrazit soubor

@@ -4,6 +4,7 @@ export const PageID = {

LOGIN: id++,
LOGOUT: id++,
CLEAR_CHANGE_CONTRACT: id++,

APP_RECEIPT_ISSUING_ORDER_INDEX: id++,
APP_RECEIPT_ISSUING_ORDER_MAIL_ORDER: id++,


+ 41
- 9
src/contexts/AuthContext.tsx Zobrazit soubor

@@ -1,6 +1,11 @@
import { HasChildren } from "@types";
import { ResultCode } from "api";
import { login as APILogin, logout as APILogout, me } from "api/auth";
import {
login as APILogin,
logout as APILogout,
changeContract as APIChangeContract,
me,
} from "api/auth";
import { CustomCode } from "codes/custom";
import { PageID } from "codes/page";
import { UserRole } from "codes/user";
@@ -27,10 +32,12 @@ type Auth = {
custom: CustomCode[];
customerName: string;

isChangedContractId: boolean;

login: (email: string, password: string) => Promise<boolean>;
logout: VoidFunction;

changeContractId: (contractId: string) => Promise<boolean>;
changeContractId: (contractId: string | null) => Promise<boolean>;

checkRole: (role?: UserRole) => boolean;
canAccess: (pageId: PageID) => boolean;
@@ -47,9 +54,11 @@ export const AuthContext = createContext<Auth>({
custom: [],
customerName: "",

isChangedContractId: false,

login: async (email: string, password: string) => false,
logout: () => {},
changeContractId: async (contractId: string) => false,
changeContractId: async (contractId: string | null) => false,
checkRole: (role?: UserRole) => false,
canAccess: (pageId: PageID) => false,
});
@@ -64,18 +73,24 @@ function AuthContextProvider({ children }: Props) {
const [custom, setCustom] = useState<CustomCode[]>([]);
const [customerName, setCustomerName] = useState("");

const isChangedContractId = useMemo(() => {
return role === UserRole.SUPER_ADMIN && contractId !== null;
}, [contractId]);

const authenticated = useMemo(() => {
return role !== UserRole.NONE;
}, [role]);

const { callAPI: callMe } = useAPICall({
apiMethod: me,
backDrop: true,
onSuccess: (res) => {
setContractId(res.data.contract_id);
setUserId(res.data.id);
setRole(res.data.role);
setName(res.data.name);
setCustom(res.data.custom ?? []);
setCustomerName(res.data.contract_name ?? "");
setInitialized(true);
},
onFailed: () => {
@@ -86,12 +101,14 @@ function AuthContextProvider({ children }: Props) {

const { callAPI: callLogin } = useAPICall({
apiMethod: APILogin,
backDrop: true,
onSuccess: (res) => {
setContractId(res.data.contract_id);
setUserId(res.data.id);
setRole(res.data.role);
setName(res.data.name);
setCustom(res.data.custom ?? []);
setCustomerName(res.data.contract_name ?? "");
setInitialized(true);
},
});
@@ -102,6 +119,16 @@ function AuthContextProvider({ children }: Props) {
clear();
},
});
const { callAPI: callChangeContract } = useAPICall({
apiMethod: APIChangeContract,
backDrop: true,
onSuccess: (res) => {
setContractId(res.data.contract_id);
setCustom(res.data.custom ?? []);
setCustomerName(res.data.contract_name ?? "");
setInitialized(true);
},
});

const clear = () => {
setRole(UserRole.NONE);
@@ -121,9 +148,9 @@ function AuthContextProvider({ children }: Props) {
callLogout({});
console.info("ログアウト");
};
const changeContractId = async (contractId: string) => {
console.error("未実装 成り代わり");
return false;
const changeContractId = async (contractId: string | null) => {
const res = await callChangeContract({ contract_id: contractId });
return res?.result === ResultCode.SUCCESS;
};

const checkRole = useCallback(
@@ -162,14 +189,19 @@ function AuthContextProvider({ children }: Props) {

return (
!!authorization &&
// 権限条件
authorization.role.includes(role) &&
// カスタム条件
(authorization.custom.length === 0 ||
!!custom.find((c) => {
return authorization.custom.includes(c);
}))
})) &&
// 成り代わり条件
(authorization.allowChangedContract === undefined ||
isChangedContractId === authorization.allowChangedContract)
);
},
[initialized, role, custom]
[initialized, role, custom, isChangedContractId]
);

useEffect(() => {
@@ -187,8 +219,8 @@ function AuthContextProvider({ children }: Props) {
userId,
name,
custom,

customerName,
isChangedContractId,

// Func
login,


+ 26
- 6
src/layouts/dashbord/navigator.tsx Zobrazit soubor

@@ -4,8 +4,9 @@ import PeopleIcon from "@mui/icons-material/People";
import ArticleIcon from "@mui/icons-material/Article";
import SettingsIcon from "@mui/icons-material/Settings";
import AccountBoxIcon from "@mui/icons-material/AccountBox";
import AccountCircleIcon from "@mui/icons-material/AccountCircle";
import AccountBalanceIcon from "@mui/icons-material/AccountBalance";
import { Collapse } from "@mui/material";
import { Collapse, Typography } from "@mui/material";
import Box from "@mui/material/Box";
import Divider from "@mui/material/Divider";
import Drawer, { DrawerProps } from "@mui/material/Drawer";
@@ -51,6 +52,12 @@ const item = {
},
};

const viewItem = {
py: "2px",
px: 3,
color: "rgba(255, 255, 255, 0.7)",
};

const itemCategory = {
boxShadow: "0 -1px 0 rgb(255,255,255,0.1) inset",
py: 1.5,
@@ -60,7 +67,7 @@ const itemCategory = {
export default function Navigator(props: DrawerProps) {
const { ...other } = props;

const { userId } = useAuth();
const { userId, customerName, name, isChangedContractId } = useAuth();

const categories: Group[] = [
{
@@ -138,6 +145,11 @@ export default function Navigator(props: DrawerProps) {
},
],
},
{
label: "成り代わり解除",
icon: <SettingsIcon />,
id: PageID.CLEAR_CHANGE_CONTRACT,
},
{ label: "ログアウト", icon: <SettingsIcon />, id: PageID.LOGOUT },
],
},
@@ -151,11 +163,18 @@ export default function Navigator(props: DrawerProps) {
>
EasyReceipt
</ListItem>
<ListItem sx={{ ...item, ...itemCategory }}>
<ListItem sx={{ ...viewItem, ...itemCategory }}>
<ListItemIcon>
<HomeIcon />
<AccountCircleIcon />
</ListItemIcon>
<ListItemText>Project Overview</ListItemText>
<ListItemText>{}</ListItemText>
<ListItemText>
<Typography>{customerName}</Typography>
<Typography>{name}</Typography>
{isChangedContractId && (
<Typography color="error">!!成り代わり中!!</Typography>
)}
</ListItemText>
</ListItem>

{categories.map((group, index) => {
@@ -188,6 +207,7 @@ function Group(group: Group) {

function SubGroup({ icon, label, id, children, option }: SubGroup) {
const { pageId } = usePage();
const { canAccess } = useAuth();
const { navigateWhenChanged } = useNavigateCustom();

const { elements, shouldOpen } = useContents(children ?? []);
@@ -219,7 +239,7 @@ function SubGroup({ icon, label, id, children, option }: SubGroup) {
);
}
// 子要素なしの場合
if (id !== undefined) {
if (id !== undefined && canAccess(id)) {
const handleClick = () => {
if (id) {
const path = getPath(id, option);


+ 26
- 0
src/pages/auth/clear-contract.tsx Zobrazit soubor

@@ -0,0 +1,26 @@
import { PageID } from "codes/page";
import useAuth from "hooks/useAuth";
import useNavigateCustom from "hooks/useNavigateCustom";
import useSnackbarCustom from "hooks/useSnackbarCustom";
import { useEffect } from "react";
import { getPath } from "routes/path";

export default function ClearChangeContract() {
const { changeContractId } = useAuth();
const { info, error } = useSnackbarCustom();

const { navigateWhenChanged } = useNavigateCustom();

useEffect(() => {
changeContractId(null).then((ret) => {
if (ret) {
info("成り代わり解除しました");
} else {
error("失敗しました");
}
navigateWhenChanged(getPath(PageID.DASHBOARD_OVERVIEW));
});
}, []);

return null;
}

+ 12
- 3
src/pages/dashboard/contract/list.tsx Zobrazit soubor

@@ -11,16 +11,19 @@ import {
Typography,
} from "@mui/material";
import { Dictionary } from "@types";
import { changeContract } from "api/auth";
import { Contract, getContracts } from "api/contract";
import { PageID, TabID } from "codes/page";
import { FormProvider, RHFTextField } from "components/hook-form";
import { TableHeadCustom } from "components/table";
import { SearchConditionContextProvider } from "contexts/SearchConditionContext";
import useAPICall from "hooks/useAPICall";
import useAuth from "hooks/useAuth";
import useBackDrop from "hooks/useBackDrop";
import useDashboard from "hooks/useDashBoard";
import useNavigateCustom from "hooks/useNavigateCustom";
import useSearchConditionContext from "hooks/useSearchConditionContext";
import useSnackbarCustom from "hooks/useSnackbarCustom";
import useTable, { UseTableReturn } from "hooks/useTable";
import { useEffect } from "react";
import { useForm } from "react-hook-form";
@@ -221,10 +224,16 @@ type RowProps = {
};
function Row({ data }: RowProps) {
const { navigateWhenChanged } = useNavigateCustom();

const { changeContractId } = useAuth();
const { info } = useSnackbarCustom();
const handleClick = () => {
navigateWhenChanged(getPath(PageID.DASHBOARD_CONTRACT_DETAIL), {
id: data.id,
// navigateWhenChanged(getPath(PageID.DASHBOARD_CONTRACT_DETAIL), {
// id: data.id,
// });

changeContractId(data.id).then((res) => {
info("成り代わりました");
navigateWhenChanged(getPath(PageID.DASHBOARD_OVERVIEW));
});
};



+ 28
- 12
src/routes/auth.ts Zobrazit soubor

@@ -5,45 +5,56 @@ import { UserRole as R } from "codes/user";
type AuthConfiguration = {
role: R[];
custom: C[];

allowChangedContract?: boolean;
};
export const AUTH = {
[P.NONE]: setAuth("all"),
[P.LOGIN]: setAuth("all"),
[P.LOGOUT]: setAuth("all"),
[P.CLEAR_CHANGE_CONTRACT]: setAuth("eq", R.SUPER_ADMIN, {
allowChangedContract: true,
}),

[P.DASHBOARD_OVERVIEW]: setAuth("ge", R.NORMAL_ADMIN),

[P.DASHBOARD_CONTRACT_LIST]: setAuth("eq", R.SUPER_ADMIN),
[P.DASHBOARD_CONTRACT_DETAIL]: setAuth("eq", R.SUPER_ADMIN),
[P.DASHBOARD_CONTRACT_CREATE]: setAuth("eq", R.SUPER_ADMIN),
[P.DASHBOARD_CONTRACT_LIST]: setAuth("eq", R.SUPER_ADMIN, {
allowChangedContract: false,
}),
[P.DASHBOARD_CONTRACT_DETAIL]: setAuth("eq", R.SUPER_ADMIN, {
allowChangedContract: false,
}),
[P.DASHBOARD_CONTRACT_CREATE]: setAuth("eq", R.SUPER_ADMIN, {
allowChangedContract: false,
}),

[P.DASHBOARD_RECEIPT_ISSUING_ORDER_CREATE_CUSTOM_HELLO_TECHNO]: setAuth(
"ge",
R.NORMAL_ADMIN,
[C.HELLO_TECHNO]
{ custom: [C.HELLO_TECHNO] }
),
[P.DASHBOARD_RECEIPT_ISSUING_ORDER_LIST_CUSTOM_HELLO_TECHNO]: setAuth(
"ge",
R.NORMAL_ADMIN,
[C.HELLO_TECHNO]
{ custom: [C.HELLO_TECHNO] }
),
[P.DASHBOARD_RECEIPT_ISSUING_ORDER_DETAIL_CUSTOM_HELLO_TECHNO]: setAuth(
"ge",
R.NORMAL_ADMIN,
[C.HELLO_TECHNO]
{ custom: [C.HELLO_TECHNO] }
),
[P.DASHBOARD_USE_SUMMARY_LIST_CUSTOM_HELLO_TECHNO]: setAuth(
"ge",
R.NORMAL_ADMIN,
[C.HELLO_TECHNO]
{ custom: [C.HELLO_TECHNO] }
),
[P.DASHBOARD_USE_SUMMARY_DETAIL_CUSTOM_HELLO_TECHNO]: setAuth(
"ge",
R.NORMAL_ADMIN,
[C.HELLO_TECHNO]
{ custom: [C.HELLO_TECHNO] }
),
[P.DASHBOARD_LOGIN_USER_LIST]: setAuth("ge", R.CONTRACT_ADMIN),
[P.DASHBOARD_LOGIN_USER_CREATE]: setAuth("ge", R.CONTRACT_ADMIN),
[P.DASHBOARD_LOGIN_USER_LIST]: setAuth("eq", R.CONTRACT_ADMIN),
[P.DASHBOARD_LOGIN_USER_CREATE]: setAuth("eq", R.CONTRACT_ADMIN),
[P.DASHBOARD_LOGIN_USER_CHANGE_PASSWORD]: setAuth("ge", R.NORMAL_ADMIN),

[P.PAGE_403]: setAuth("all"),
@@ -52,10 +63,14 @@ export const AUTH = {

type Target = "ge" | "le" | "eq" | "all";
type UserRoleKey = keyof typeof R;
type OptionProps = {
custom?: C[];
allowChangedContract?: boolean;
};
function setAuth(
target: Target,
targetRole?: R,
custom: C[] = []
option?: OptionProps
): AuthConfiguration {
const roles: R[] = [];

@@ -87,6 +102,7 @@ function setAuth(

return {
role: roles,
custom: custom,
custom: option?.custom ?? [],
allowChangedContract: option?.allowChangedContract,
};
}

+ 5
- 0
src/routes/index.tsx Zobrazit soubor

@@ -28,6 +28,10 @@ const AuthRoutes = (): RouteObject => ({
path: getRoute(PageID.LOGOUT),
element: <Logout />,
},
{
path: getRoute(PageID.CLEAR_CHANGE_CONTRACT),
element: <ClearContract />,
},
],
});

@@ -138,6 +142,7 @@ export function Routes() {
// 認証関連 -------------------------------
const Login = Loadable(lazy(() => import("pages/auth/login")));
const Logout = Loadable(lazy(() => import("pages/auth/logout")));
const ClearContract = Loadable(lazy(() => import("pages/auth/clear-contract")));

// App ---------------------------
const ReceiptIssuingOrder = Loadable(


+ 1
- 0
src/routes/path.ts Zobrazit soubor

@@ -34,6 +34,7 @@ const PATHS = {
// 認証
[makePathKey(PageID.LOGIN)]: "/login",
[makePathKey(PageID.LOGOUT)]: "/logout",
[makePathKey(PageID.CLEAR_CHANGE_CONTRACT)]: "/clear-change-contract",

[makePathKey(PageID.DASHBOARD_OVERVIEW)]: "/dashboard",



Načítá se…
Zrušit
Uložit