ソースを参照

Merge branch 'master' of https://git.2fi-solutions.com/derek/FPSMS-frontend

feature/axios_provider
MSI\derek 4ヶ月前
コミット
92e3da278d
11個のファイルの変更328行の追加0行の削除
  1. +44
    -0
      src/app/(main)/settings/qcCategory/page.tsx
  2. +17
    -0
      src/app/(main)/settings/qcItem/create/not-found.tsx
  3. +24
    -0
      src/app/(main)/settings/qcItem/create/page.tsx
  4. +17
    -0
      src/app/(main)/settings/qcItem/edit/not-found.tsx
  5. +49
    -0
      src/app/(main)/settings/qcItem/edit/page.tsx
  6. +17
    -0
      src/app/api/settings/qcCategory/actions.ts
  7. +20
    -0
      src/app/api/settings/qcCategory/index.ts
  8. +76
    -0
      src/components/QcCategorySearch/QcCategorySearch.tsx
  9. +40
    -0
      src/components/QcCategorySearch/QcCategorySearchLoading.tsx
  10. +23
    -0
      src/components/QcCategorySearch/QcCategorySearchWrapper.tsx
  11. +1
    -0
      src/components/QcCategorySearch/index.ts

+ 44
- 0
src/app/(main)/settings/qcCategory/page.tsx ファイルの表示

@@ -0,0 +1,44 @@
import { Metadata } from "next";
import { getServerI18n, I18nProvider } from "@/i18n";
import Typography from "@mui/material/Typography";
import { Button, Link, Stack } from "@mui/material";
import { Add } from "@mui/icons-material";
import { Suspense } from "react";
import QcCategorySearch from "@/components/QcCategorySearch";
import { preloadQcCategory } from "@/app/api/settings/qcCategory";

export const metadata: Metadata = {
title: "Qc Category",
};

const qcCategory: React.FC = async () => {
const { t } = await getServerI18n("qcCategory")

preloadQcCategory()

return <>
<Stack
direction="row"
justifyContent="space-between"
flexWrap="wrap"
rowGap={2}
>
<Typography variant="h4" marginInlineEnd={2}>
{t("Qc Category")}
</Typography>
<Button
variant="contained"
startIcon={<Add />}
LinkComponent={Link}
href="qcCategory/create"
>
{t("Create Qc Category")}
</Button>
</Stack>
<Suspense fallback={<QcCategorySearch.Loading />}>
<QcCategorySearch />
</Suspense>
</>;
};

export default qcCategory;

+ 17
- 0
src/app/(main)/settings/qcItem/create/not-found.tsx ファイルの表示

@@ -0,0 +1,17 @@
import { getServerI18n } from "@/i18n";
import { Stack, Typography, Link } from "@mui/material";
import NextLink from "next/link";

export default async function NotFound() {
const { t } = await getServerI18n("qcItem", "common");

return (
<Stack spacing={2}>
<Typography variant="h4">{t("Not Found")}</Typography>
<Typography variant="body1">{t("The create qc item page was not found!")}</Typography>
<Link href="/qcItems" component={NextLink} variant="body2">
{t("Return to all qc items")}
</Link>
</Stack>
);
}

+ 24
- 0
src/app/(main)/settings/qcItem/create/page.tsx ファイルの表示

@@ -0,0 +1,24 @@
import { Metadata } from "next";
import { getServerI18n, I18nProvider } from "@/i18n";
import Typography from "@mui/material/Typography";
import { preloadQcItem } from "@/app/api/settings/qcItem";
import QcItemSave from "@/components/QcItemSave";

export const metadata: Metadata = {
title: "Qc Item",
};

const qcItem: React.FC = async () => {
const { t } = await getServerI18n("qcItem")

return <>
<Typography variant="h4" marginInlineEnd={2}>
{t("Create Qc Item")}
</Typography>
<I18nProvider namespaces={["qcItem"]}>
<QcItemSave />
</I18nProvider>
</>;
};

export default qcItem;

+ 17
- 0
src/app/(main)/settings/qcItem/edit/not-found.tsx ファイルの表示

@@ -0,0 +1,17 @@
import { getServerI18n } from "@/i18n";
import { Stack, Typography, Link } from "@mui/material";
import NextLink from "next/link";

export default async function NotFound() {
const { t } = await getServerI18n("qcItem", "common");

return (
<Stack spacing={2}>
<Typography variant="h4">{t("Not Found")}</Typography>
<Typography variant="body1">{t("The edit qc item page was not found!")}</Typography>
<Link href="/qcItems" component={NextLink} variant="body2">
{t("Return to all qc items")}
</Link>
</Stack>
);
}

+ 49
- 0
src/app/(main)/settings/qcItem/edit/page.tsx ファイルの表示

@@ -0,0 +1,49 @@
import { Metadata } from "next";
import { getServerI18n, I18nProvider } from "@/i18n";
import Typography from "@mui/material/Typography";
import { fetchQcItemDetails, preloadQcItem } from "@/app/api/settings/qcItem";
import QcItemSave from "@/components/QcItemSave";
import { isArray } from "lodash";
import { notFound } from "next/navigation";
import { ServerFetchError } from "@/app/utils/fetchUtil";

export const metadata: Metadata = {
title: "Qc Item",
};

interface Props {
searchParams: { [key: string]: string | string[] | undefined };
}

const qcItem: React.FC<Props> = async ({ searchParams }) => {
const { t } = await getServerI18n("qcItem")

const id = searchParams["id"]

if (!id || isArray(id)) {
notFound()
}

try {
console.log("first")
await fetchQcItemDetails(id)
console.log("firsts")
} catch (e) {

if (e instanceof ServerFetchError && (e.response?.status === 404 || e.response?.status === 400)) {
console.log(e)
notFound();
}
}

return <>
<Typography variant="h4" marginInlineEnd={2}>
{t("Edit Qc Item")}
</Typography>
<I18nProvider namespaces={["qcItem"]}>
<QcItemSave id={id}/>
</I18nProvider>
</>;
};

export default qcItem;

+ 17
- 0
src/app/api/settings/qcCategory/actions.ts ファイルの表示

@@ -0,0 +1,17 @@
"use server"

import { serverFetchJson } from "@/app/utils/fetchUtil";
import { BASE_API_URL } from "@/config/api";

export interface CreateQcCategoryInputs {
code: string;
name: string;
}

export const saveQcCategory = async (data: CreateQcCategoryInputs) => {
return serverFetchJson(`${BASE_API_URL}/qcCategories/save`, {
method: "POST",
body: JSON.stringify(data),
headers: { "Content-Type": "application/json" },
})
}

+ 20
- 0
src/app/api/settings/qcCategory/index.ts ファイルの表示

@@ -0,0 +1,20 @@
import { serverFetchJson } from "@/app/utils/fetchUtil";
import { BASE_API_URL } from "@/config/api";
import { cache } from "react";
import "server-only";

export interface QcCategoryResult {
id: number;
code: string;
name: string;
}

export const preloadQcCategory = () => {
fetchQcCategories();
};

export const fetchQcCategories = cache(async () => {
return serverFetchJson<QcCategoryResult[]>(`${BASE_API_URL}/qcCategories`, {
next: { tags: ["qcCategories"]}
});
});

+ 76
- 0
src/components/QcCategorySearch/QcCategorySearch.tsx ファイルの表示

@@ -0,0 +1,76 @@
"use client";

import React, { useCallback, useMemo, useState } from "react";
import SearchBox, { Criterion } from "../SearchBox";
import { useTranslation } from "react-i18next";
import SearchResults, { Column } from "../SearchResults";
import EditNote from "@mui/icons-material/EditNote";
import { QcCategoryResult } from "@/app/api/settings/qcCategory";

interface Props {
qcCategories: QcCategoryResult[];
}

type SearchQuery = Partial<Omit<QcCategoryResult, "id">>;
type SearchParamNames = keyof SearchQuery;

const QcCategorySearch: React.FC<Props> = ({ qcCategories }) => {
const { t } = useTranslation("qcCategories");

// If qcCategory searching is done on the server-side, then no need for this.
const [filteredQcCategories, setFilteredQcCategories] = useState(qcCategories);

const searchCriteria: Criterion<SearchParamNames>[] = useMemo(
() => [
{ label: t("Code"), paramName: "code", type: "text" },
{ label: t("Name"), paramName: "name", type: "text" },
],
[t],
);

const onReset = useCallback(() => {
setFilteredQcCategories(qcCategories);
}, [qcCategories]);

const onQcCategoryClick = useCallback((qcCategory: QcCategoryResult) => {
console.log(qcCategory);
}, []);

const columns = useMemo<Column<QcCategoryResult>[]>(
() => [
{
name: "id",
label: t("Details"),
onClick: onQcCategoryClick,
buttonIcon: <EditNote />,
},
{ name: "code", label: t("Code") },
{ name: "name", label: t("Name") },
],
[t, onQcCategoryClick],
);

return (
<>
<SearchBox
criteria={searchCriteria}
onSearch={(query) => {
setFilteredQcCategories(
qcCategories.filter(
(qc) =>
qc.code.toLowerCase().includes(query.code.toLowerCase()) &&
qc.name.toLowerCase().includes(query.name.toLowerCase())
),
);
}}
onReset={onReset}
/>
<SearchResults<QcCategoryResult>
items={filteredQcCategories}
columns={columns}
/>
</>
);
};

export default QcCategorySearch;

+ 40
- 0
src/components/QcCategorySearch/QcCategorySearchLoading.tsx ファイルの表示

@@ -0,0 +1,40 @@
import Card from "@mui/material/Card";
import CardContent from "@mui/material/CardContent";
import Skeleton from "@mui/material/Skeleton";
import Stack from "@mui/material/Stack";
import React from "react";

// Can make this nicer
export const QcCategorySearchLoading: React.FC = () => {
return (
<>
<Card>
<CardContent>
<Stack spacing={2}>
<Skeleton variant="rounded" height={60} />
<Skeleton variant="rounded" height={60} />
<Skeleton variant="rounded" height={60} />
<Skeleton
variant="rounded"
height={50}
width={100}
sx={{ alignSelf: "flex-end" }}
/>
</Stack>
</CardContent>
</Card>
<Card>
<CardContent>
<Stack spacing={2}>
<Skeleton variant="rounded" height={40} />
<Skeleton variant="rounded" height={40} />
<Skeleton variant="rounded" height={40} />
<Skeleton variant="rounded" height={40} />
</Stack>
</CardContent>
</Card>
</>
);
};

export default QcCategorySearchLoading;

+ 23
- 0
src/components/QcCategorySearch/QcCategorySearchWrapper.tsx ファイルの表示

@@ -0,0 +1,23 @@
import React from "react"
import QcCategorySearchLoading from "./QcCategorySearchLoading"
import QcCategorySearch from "./QcCategorySearch";
import { fetchQcCategories } from "@/app/api/settings/qcCategory";

interface SubComponents {
Loading: typeof QcCategorySearchLoading;
}

const QcCategorySearchWrapper: React.FC & SubComponents = async () => {

const [
qcCategories
] = await Promise.all([
fetchQcCategories()
]);

return <QcCategorySearch qcCategories={qcCategories} />;
};

QcCategorySearchWrapper.Loading = QcCategorySearchLoading;

export default QcCategorySearchWrapper;

+ 1
- 0
src/components/QcCategorySearch/index.ts ファイルの表示

@@ -0,0 +1 @@
export { default } from "./QcCategorySearchWrapper";

読み込み中…
キャンセル
保存