From de831e710b679bfaf18b26ac32f63d9b52294c6e Mon Sep 17 00:00:00 2001 From: shunsei Date: Sun, 27 Oct 2024 14:44:56 +0900 Subject: [PATCH 1/6] Add prettier config (#97) --- backend/.prettierrc => .prettierrc | 3 +- .vscode/settings.json | 4 +- backend/package.json | 110 +++++++++++----------- frontend/.prettierignore | 21 +++++ frontend/package.json | 141 +++++++++++++++-------------- 5 files changed, 152 insertions(+), 127 deletions(-) rename backend/.prettierrc => .prettierrc (58%) create mode 100644 frontend/.prettierignore diff --git a/backend/.prettierrc b/.prettierrc similarity index 58% rename from backend/.prettierrc rename to .prettierrc index ab03510a..295f0916 100644 --- a/backend/.prettierrc +++ b/.prettierrc @@ -2,5 +2,6 @@ "printWidth": 80, "singleQuote": true, "semi": true, - "useTabs": true + "useTabs": true, + "trailingComma": "all" } diff --git a/.vscode/settings.json b/.vscode/settings.json index 3370f514..e40d8393 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,6 +1,8 @@ { + "editor.defaultFormatter": "esbenp.prettier-vscode", "editor.formatOnSave": true, "editor.codeActionsOnSave": { "source.fixAll.eslint": "explicit" - } + }, + "prettier.configPath": ".prettierrc", } diff --git a/backend/package.json b/backend/package.json index 9d1d0226..1aff1f33 100644 --- a/backend/package.json +++ b/backend/package.json @@ -1,57 +1,57 @@ { - "name": "kitcc-library-api", - "version": "0.0.0", - "private": true, - "type": "module", - "packageManager": "pnpm@9.12.0", - "scripts": { - "deploy": "wrangler deploy", - "dev": "wrangler dev", - "format": "npx prettier . --write", - "lint": "npx eslint --fix --cache --cache-location ./node_modules/.cache/eslint .", - "start": "wrangler dev", - "test": "vitest", - "cf-typegen": "wrangler types", - "db:mig:gen": "pnpm drizzle-kit generate", - "db:mig:ls": "wrangler d1 migrations list kitcc-lib-db", - "db:mig:apply": "wrangler d1 migrations apply kitcc-lib-db", - "db:seed": "wrangler d1 execute kitcc-lib-db --file=./drizzle/seeds/${file}", - "db:studio": "drizzle-kit studio --config drizzle.config.local.ts", - "prepare": "husky" - }, - "lint-staged": { - "*.{ts, tsx, js, jsx}": [ - "prettier --write", - "eslint --fix" - ] - }, - "devDependencies": { - "@cloudflare/vitest-pool-workers": "^0.5.16", - "@cloudflare/workers-types": "^4.20241004.0", - "@eslint/compat": "^1.2.1", - "@eslint/js": "^9.13.0", - "@faker-js/faker": "^9.0.3", - "@types/node": "^22.7.5", - "better-sqlite3": "^11.3.0", - "drizzle-kit": "^0.24.2", - "eslint": "^9.13.0", - "eslint-config-prettier": "^9.1.0", - "factory.ts": "^1.4.1", - "husky": "^9.1.6", - "lint-staged": "^15.2.10", - "orval": "^7.1.1", - "prettier": "3.3.3", - "tsx": "^4.19.1", - "typescript": "^5.6.3", - "vitest": "2.0.5", - "wrangler": "^3.80.2" - }, - "dependencies": { - "@hono/zod-validator": "^0.3.0", - "camelcase": "^8.0.0", - "drizzle-orm": "^0.33.0", - "hono": "^4.6.3", - "jsonpath-plus": "^10.0.0", - "zod": "^3.23.8" - } + "name": "kitcc-library-api", + "version": "0.0.0", + "private": true, + "type": "module", + "packageManager": "pnpm@9.12.0", + "scripts": { + "deploy": "wrangler deploy", + "dev": "wrangler dev", + "format": "npx prettier . --write --config ../.prettierrc", + "lint": "npx eslint --fix --cache --cache-location ./node_modules/.cache/eslint .", + "start": "wrangler dev", + "test": "vitest", + "cf-typegen": "wrangler types", + "db:mig:gen": "pnpm drizzle-kit generate", + "db:mig:ls": "wrangler d1 migrations list kitcc-lib-db", + "db:mig:apply": "wrangler d1 migrations apply kitcc-lib-db", + "db:seed": "wrangler d1 execute kitcc-lib-db --file=./drizzle/seeds/${file}", + "db:studio": "drizzle-kit studio --config drizzle.config.local.ts", + "prepare": "husky" + }, + "lint-staged": { + "*.{ts, tsx, js, jsx}": [ + "prettier --write", + "eslint --fix" + ] + }, + "devDependencies": { + "@cloudflare/vitest-pool-workers": "^0.5.16", + "@cloudflare/workers-types": "^4.20241004.0", + "@eslint/compat": "^1.2.1", + "@eslint/js": "^9.13.0", + "@faker-js/faker": "^9.0.3", + "@types/node": "^22.7.5", + "better-sqlite3": "^11.3.0", + "drizzle-kit": "^0.24.2", + "eslint": "^9.13.0", + "eslint-config-prettier": "^9.1.0", + "factory.ts": "^1.4.1", + "husky": "^9.1.6", + "lint-staged": "^15.2.10", + "orval": "^7.1.1", + "prettier": "3.3.3", + "tsx": "^4.19.1", + "typescript": "^5.6.3", + "vitest": "2.0.5", + "wrangler": "^3.80.2" + }, + "dependencies": { + "@hono/zod-validator": "^0.3.0", + "camelcase": "^8.0.0", + "drizzle-orm": "^0.33.0", + "hono": "^4.6.3", + "jsonpath-plus": "^10.0.0", + "zod": "^3.23.8" + } } diff --git a/frontend/.prettierignore b/frontend/.prettierignore new file mode 100644 index 00000000..b6d76463 --- /dev/null +++ b/frontend/.prettierignore @@ -0,0 +1,21 @@ +# dependencies +node_modules/ + +# production +public/ + +#orval +client/ +test/mocks/ + +# misc +.DS_Store +*.pem + +.eslintrc.cjs +postcss.config.cjs +postcss.config.js +package.json +pnpm-lock.yaml +tsconfig.json +vite.config.ts diff --git a/frontend/package.json b/frontend/package.json index a4b6f2b6..fd1e4b0b 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,72 +1,73 @@ { - "name": "kitcc-library-web", - "private": true, - "sideEffects": false, - "type": "module", - "scripts": { - "build": "remix vite:build", - "deploy": "pnpm run build && wrangler pages deploy", - "dev": "NODE_TLS_REJECT_UNAUTHORIZED=0 remix vite:dev", - "lint": "eslint --ignore-path .gitignore --cache --cache-location ./node_modules/.cache/eslint .", - "test": "vitest", - "start": "wrangler pages dev ./build/client", - "typecheck": "tsc", - "typegen": "wrangler types", - "preview": "pnpm run build && wrangler pages dev", - "cf-typegen": "wrangler types" - }, - "dependencies": { - "@mantine/core": "^7.13.2", - "@mantine/form": "^7.13.2", - "@mantine/hooks": "^7.13.2", - "@mantine/notifications": "^7.13.3", - "@remix-run/cloudflare": "2.12.0", - "@remix-run/cloudflare-pages": "2.12.0", - "@remix-run/react": "2.12.0", - "@tanstack/react-query": "^5.59.15", - "add": "^2.0.6", - "isbot": "^4.1.0", - "jotai": "^2.10.1", - "jsonpath-plus": "^10.0.0", - "react": "19.0.0-rc-09111202-20241011", - "react-dom": "19.0.0-rc-09111202-20241011", - "react-icons": "^5.3.0" - }, - "overrides": { - "@types/react": "npm:types-react@rc", - "@types/react-dom": "npm:types-react-dom@rc" - }, - "devDependencies": { - "@cloudflare/workers-types": "^4.20241004.0", - "@faker-js/faker": "^9.0.3", - "@remix-run/dev": "2.12.0", - "@testing-library/jest-dom": "^6.6.2", - "@testing-library/react": "^16.0.1", - "@testing-library/user-event": "^14.5.2", - "@types/react": "npm:types-react@19.0.0-rc.1", - "@types/react-dom": "npm:types-react-dom@19.0.0-rc.1", - "@typescript-eslint/eslint-plugin": "^6.7.4", - "@typescript-eslint/parser": "^6.7.4", - "autoprefixer": "^10.4.19", - "eslint": "^8.57.1", - "eslint-import-resolver-typescript": "^3.6.1", - "eslint-plugin-import": "^2.28.1", - "eslint-plugin-jsx-a11y": "^6.7.1", - "eslint-plugin-react": "^7.33.2", - "eslint-plugin-react-hooks": "^4.6.0", - "happy-dom": "^15.7.4", - "msw": "^2.5.1", - "orval": "^7.1.1", - "postcss": "^8.4.47", - "postcss-preset-mantine": "^1.17.0", - "postcss-simple-vars": "^7.0.1", - "typescript": "^5.1.6", - "vite": "^5.1.0", - "vite-tsconfig-paths": "^4.2.1", - "vitest": "^2.1.3", - "wrangler": "3.57.1" - }, - "engines": { - "node": ">=20.0.0" - } + "name": "kitcc-library-web", + "private": true, + "sideEffects": false, + "type": "module", + "scripts": { + "build": "remix vite:build", + "deploy": "pnpm run build && wrangler pages deploy", + "dev": "NODE_TLS_REJECT_UNAUTHORIZED=0 remix vite:dev", + "format": "npx prettier . --write --config ../.prettierrc", + "lint": "eslint --ignore-path .gitignore --cache --cache-location ./node_modules/.cache/eslint .", + "test": "vitest", + "start": "wrangler pages dev ./build/client", + "typecheck": "tsc", + "typegen": "wrangler types", + "preview": "pnpm run build && wrangler pages dev", + "cf-typegen": "wrangler types" + }, + "dependencies": { + "@mantine/core": "^7.13.2", + "@mantine/form": "^7.13.2", + "@mantine/hooks": "^7.13.2", + "@mantine/notifications": "^7.13.3", + "@remix-run/cloudflare": "2.12.0", + "@remix-run/cloudflare-pages": "2.12.0", + "@remix-run/react": "2.12.0", + "@tanstack/react-query": "^5.59.15", + "add": "^2.0.6", + "isbot": "^4.1.0", + "jotai": "^2.10.1", + "jsonpath-plus": "^10.0.0", + "react": "19.0.0-rc-09111202-20241011", + "react-dom": "19.0.0-rc-09111202-20241011", + "react-icons": "^5.3.0" + }, + "overrides": { + "@types/react": "npm:types-react@rc", + "@types/react-dom": "npm:types-react-dom@rc" + }, + "devDependencies": { + "@cloudflare/workers-types": "^4.20241004.0", + "@faker-js/faker": "^9.0.3", + "@remix-run/dev": "2.12.0", + "@testing-library/jest-dom": "^6.6.2", + "@testing-library/react": "^16.0.1", + "@testing-library/user-event": "^14.5.2", + "@types/react": "npm:types-react@19.0.0-rc.1", + "@types/react-dom": "npm:types-react-dom@19.0.0-rc.1", + "@typescript-eslint/eslint-plugin": "^6.7.4", + "@typescript-eslint/parser": "^6.7.4", + "autoprefixer": "^10.4.19", + "eslint": "^8.57.1", + "eslint-import-resolver-typescript": "^3.6.1", + "eslint-plugin-import": "^2.28.1", + "eslint-plugin-jsx-a11y": "^6.7.1", + "eslint-plugin-react": "^7.33.2", + "eslint-plugin-react-hooks": "^4.6.0", + "happy-dom": "^15.7.4", + "msw": "^2.5.1", + "orval": "^7.1.1", + "postcss": "^8.4.47", + "postcss-preset-mantine": "^1.17.0", + "postcss-simple-vars": "^7.0.1", + "typescript": "^5.1.6", + "vite": "^5.1.0", + "vite-tsconfig-paths": "^4.2.1", + "vitest": "^2.1.3", + "wrangler": "3.57.1" + }, + "engines": { + "node": ">=20.0.0" + } } From 7c11143fe3f64164218ff271daf1a48fb8942948 Mon Sep 17 00:00:00 2001 From: shunsei Date: Sun, 27 Oct 2024 14:47:05 +0900 Subject: [PATCH 2/6] Format all frontend files (#97) --- .../book-detail/BookDetailAuthorBadge.tsx | 30 +- .../book-detail/BookDetailBorrower.tsx | 84 ++--- .../book-detail/BookDetailComponent.tsx | 58 +-- .../book-detail/BookDetailContent.tsx | 46 +-- .../book-detail/BookDetailContentTable.tsx | 74 ++-- .../book-detail/BookDetailControlPanel.tsx | 85 +++-- .../book-detail/BookDetailDescription.tsx | 14 +- .../book-detail/BookDetailThumbnail.tsx | 30 +- .../book-detail/BookDetailTitle.tsx | 12 +- .../book-search/BookSearchAuthorForm.tsx | 30 +- .../book-search/BookSearchComponent.tsx | 46 +-- .../components/book-search/BookSearchForm.tsx | 52 +-- .../book-search/BookSearchIsbnForm.tsx | 30 +- .../book-search/BookSearchModeButton.tsx | 31 +- .../book-search/BookSearchPublisherForm.tsx | 30 +- .../book-search/BookSearchSubmitButton.tsx | 21 +- .../book-search/BookSearchTitleForm.tsx | 30 +- frontend/app/components/books/BookCard.tsx | 40 +- .../components/books/BookCardCartButton.tsx | 46 +-- .../app/components/books/BookCardFooter.tsx | 24 +- .../app/components/books/BookCardHeader.tsx | 64 ++-- .../components/books/BookCardHeaderBadge.tsx | 22 +- .../components/books/BookCardThumbnail.tsx | 38 +- frontend/app/components/books/BookCards.tsx | 66 ++-- .../components/books/BookListComponent.tsx | 124 +++---- .../components/books/BookSelectedDialog.tsx | 70 ++-- .../app/components/books/NoBookComponent.tsx | 22 +- .../app/components/common/ContentsHeader.tsx | 48 ++- .../common/CurrentContentNumber.tsx | 30 +- .../app/components/common/ErrorComponent.tsx | 25 +- .../app/components/common/LimitSelect.tsx | 26 +- .../components/common/PaginationComponent.tsx | 46 +-- .../app/components/header/HeaderBookMenu.tsx | 65 ++-- .../app/components/header/HeaderComponent.tsx | 64 ++-- .../components/header/HeaderLoginButton.tsx | 26 +- .../header/HeaderLoginComponent.tsx | 124 +++---- .../header/HeaderLogoutComponent.tsx | 22 +- .../components/header/HeaderMainComponent.tsx | 16 +- .../app/components/header/HeaderTitleLogo.tsx | 28 +- .../app/components/header/HeaderUserMenu.tsx | 62 ++-- .../app/components/header/HeaderUsersMenu.tsx | 52 +-- .../app/components/layouts/FormBaseLayout.tsx | 31 +- .../app/components/layouts/FormLayout.tsx | 32 +- .../app/components/login/LoginEmailForm.tsx | 28 +- .../components/login/LoginFormComponent.tsx | 52 +-- .../components/login/LoginFormHelpText.tsx | 21 +- .../app/components/login/LoginFormTitle.tsx | 20 +- .../components/login/LoginPasswordForm.tsx | 28 +- .../components/login/LoginSubmitButton.tsx | 23 +- frontend/app/components/login/LoginTitle.tsx | 20 +- frontend/app/entry.client.tsx | 18 +- frontend/app/entry.server.tsx | 62 ++-- frontend/app/root.tsx | 78 ++-- frontend/app/routes/_index.tsx | 14 +- frontend/app/routes/auth.login.tsx | 154 ++++---- frontend/app/routes/home._index.tsx | 346 +++++++++--------- frontend/app/routes/home.books.$bookId.tsx | 78 ++-- frontend/app/routes/home.mypage.tsx | 8 +- frontend/app/routes/home.tsx | 33 +- frontend/app/stores/cartAtom.ts | 10 +- frontend/app/stores/userAtom.ts | 10 +- frontend/app/utils/notification.ts | 28 +- frontend/functions/[[path]].ts | 4 +- frontend/load-context.ts | 14 +- frontend/test/helpers/wrapper.tsx | 52 +-- frontend/test/routes/auth.login.test.tsx | 152 ++++---- frontend/test/setup.ts | 36 +- frontend/worker-configuration.d.ts | 3 +- 68 files changed, 1609 insertions(+), 1599 deletions(-) diff --git a/frontend/app/components/book-detail/BookDetailAuthorBadge.tsx b/frontend/app/components/book-detail/BookDetailAuthorBadge.tsx index d2fa0aa9..a4f5ef80 100644 --- a/frontend/app/components/book-detail/BookDetailAuthorBadge.tsx +++ b/frontend/app/components/book-detail/BookDetailAuthorBadge.tsx @@ -1,21 +1,21 @@ -import { Badge } from '@mantine/core' +import { Badge } from '@mantine/core'; interface BookDetailAuthorBadgeProps { - name: string + name: string; } const BookDetailAuthorBadge = ({ name }: BookDetailAuthorBadgeProps) => { - return ( - - {name} - - ) -} + return ( + + {name} + + ); +}; -export default BookDetailAuthorBadge \ No newline at end of file +export default BookDetailAuthorBadge; diff --git a/frontend/app/components/book-detail/BookDetailBorrower.tsx b/frontend/app/components/book-detail/BookDetailBorrower.tsx index f2646700..5709477a 100644 --- a/frontend/app/components/book-detail/BookDetailBorrower.tsx +++ b/frontend/app/components/book-detail/BookDetailBorrower.tsx @@ -1,49 +1,49 @@ import { - Badge, - Blockquote, - Group, - Loader, - rem, - Stack, - Text, -} from "@mantine/core"; -import { useGetLoans } from "client/client"; -import { MdError } from "react-icons/md"; + Badge, + Blockquote, + Group, + Loader, + rem, + Stack, + Text, +} from '@mantine/core'; +import { useGetLoans } from 'client/client'; +import { MdError } from 'react-icons/md'; const BookDetailBorrower = () => { - const loans = useGetLoans(); + const loans = useGetLoans(); - if (loans.isError) { - return ( -
} mt="xl"> - データの取得に失敗しました -
- ); - } - return ( - - 借りている人 - {loans.isPending ? ( - - ) : ( - - {loans.data.data.loans.map( - (loan) => - loan.users && ( - - {loan.users.name} - - ) - )} - - )} - - ); + if (loans.isError) { + return ( +
} mt="xl"> + データの取得に失敗しました +
+ ); + } + return ( + + 借りている人 + {loans.isPending ? ( + + ) : ( + + {loans.data.data.loans.map( + (loan) => + loan.users && ( + + {loan.users.name} + + ), + )} + + )} + + ); }; export default BookDetailBorrower; diff --git a/frontend/app/components/book-detail/BookDetailComponent.tsx b/frontend/app/components/book-detail/BookDetailComponent.tsx index 920c2b61..603f6f10 100644 --- a/frontend/app/components/book-detail/BookDetailComponent.tsx +++ b/frontend/app/components/book-detail/BookDetailComponent.tsx @@ -1,39 +1,39 @@ -import { Grid, rem, Stack } from "@mantine/core"; -import ErrorComponent from "~/components/common/ErrorComponent"; +import { Grid, rem, Stack } from '@mantine/core'; +import ErrorComponent from '~/components/common/ErrorComponent'; -import { getBookResponse } from "client/client"; -import BookDetailContent from "./BookDetailContent"; -import BookDetailControlPanel from "./BookDetailControlPanel"; +import { getBookResponse } from 'client/client'; +import BookDetailContent from './BookDetailContent'; +import BookDetailControlPanel from './BookDetailControlPanel'; interface BookDetailComponentProps { - bookResponse: getBookResponse; + bookResponse: getBookResponse; } const BookDetailComponent = ({ bookResponse }: BookDetailComponentProps) => { - switch (bookResponse.status) { - case 400: - return ; - case 404: - return ; - case 500: - return ; - } + switch (bookResponse.status) { + case 400: + return ; + case 404: + return ; + case 500: + return ; + } - return ( - - - - - - - - - - - ); + return ( + + + + + + + + + + + ); }; export default BookDetailComponent; diff --git a/frontend/app/components/book-detail/BookDetailContent.tsx b/frontend/app/components/book-detail/BookDetailContent.tsx index ed0237ab..0463b9b5 100644 --- a/frontend/app/components/book-detail/BookDetailContent.tsx +++ b/frontend/app/components/book-detail/BookDetailContent.tsx @@ -1,31 +1,31 @@ -import { Stack } from "@mantine/core"; -import { Book } from "client/client.schemas"; -import { useAtom } from "jotai"; -import { userAtom } from "~/stores/userAtom"; -import BookDetailBorrower from "./BookDetailBorrower"; -import BookDetailContentTable from "./BookDetailContentTable"; -import BookDetailDescription from "./BookDetailDescription"; -import BookDetailTitle from "./BookDetailTitle"; +import { Stack } from '@mantine/core'; +import { Book } from 'client/client.schemas'; +import { useAtom } from 'jotai'; +import { userAtom } from '~/stores/userAtom'; +import BookDetailBorrower from './BookDetailBorrower'; +import BookDetailContentTable from './BookDetailContentTable'; +import BookDetailDescription from './BookDetailDescription'; +import BookDetailTitle from './BookDetailTitle'; interface BookDetailComponentProps { - book: Book; + book: Book; } const BookDetailContent = ({ book }: BookDetailComponentProps) => { - const [user] = useAtom(userAtom); - return ( - - - - - {!!user && } - - ); + const [user] = useAtom(userAtom); + return ( + + + + + {!!user && } + + ); }; export default BookDetailContent; diff --git a/frontend/app/components/book-detail/BookDetailContentTable.tsx b/frontend/app/components/book-detail/BookDetailContentTable.tsx index 0fc95725..1ad9c626 100644 --- a/frontend/app/components/book-detail/BookDetailContentTable.tsx +++ b/frontend/app/components/book-detail/BookDetailContentTable.tsx @@ -1,45 +1,45 @@ -import { Group, rem, Stack, Table, Text } from "@mantine/core"; -import { Book } from "client/client.schemas"; -import BookDetailAuthorBadge from "./BookDetailAuthorBadge"; +import { Group, rem, Stack, Table, Text } from '@mantine/core'; +import { Book } from 'client/client.schemas'; +import BookDetailAuthorBadge from './BookDetailAuthorBadge'; interface BookDetailContentTableProps { - book: Book; + book: Book; } const BookDetailContentTable = ({ book }: BookDetailContentTableProps) => { - return ( - - 書籍情報 - - - 著者 - - - {book.authors.map((author, id) => ( - - ))} - - - - - 出版社 - {book.publisher} - - - 出版日 - {book.publishedDate} - - - ISBN - {book.isbn} - - - 在庫数 - {book.stock} - -
-
- ); + return ( + + 書籍情報 + + + 著者 + + + {book.authors.map((author, id) => ( + + ))} + + + + + 出版社 + {book.publisher} + + + 出版日 + {book.publishedDate} + + + ISBN + {book.isbn} + + + 在庫数 + {book.stock} + +
+
+ ); }; export default BookDetailContentTable; diff --git a/frontend/app/components/book-detail/BookDetailControlPanel.tsx b/frontend/app/components/book-detail/BookDetailControlPanel.tsx index 8db23761..7005f4dd 100644 --- a/frontend/app/components/book-detail/BookDetailControlPanel.tsx +++ b/frontend/app/components/book-detail/BookDetailControlPanel.tsx @@ -1,48 +1,53 @@ -import { Button, Stack } from '@mantine/core' -import BookDetailThumbnail from './BookDetailThumbnail' -import { MdEdit, MdDeleteForever } from "react-icons/md"; +import { Button, Stack } from '@mantine/core'; +import BookDetailThumbnail from './BookDetailThumbnail'; +import { MdEdit, MdDeleteForever } from 'react-icons/md'; import { useAtom } from 'jotai'; import { userAtom } from '~/stores/userAtom'; import { Form, useFetcher, useNavigate } from '@remix-run/react'; interface BookDetailControlPanelProps { - id: number - thumbnail?: string + id: number; + thumbnail?: string; } -const BookDetailControlPanel = ({ id, thumbnail }: BookDetailControlPanelProps) => { - const [user,] = useAtom(userAtom) - const fetcher = useFetcher() - const navigate = useNavigate() - return ( - - - {!!user && - } - {!!user && - } - - ) -} +const BookDetailControlPanel = ({ + id, + thumbnail, +}: BookDetailControlPanelProps) => { + const [user] = useAtom(userAtom); + const fetcher = useFetcher(); + const navigate = useNavigate(); + return ( + + + {!!user && ( + + )} + {!!user && ( + + )} + + ); +}; -export default BookDetailControlPanel \ No newline at end of file +export default BookDetailControlPanel; diff --git a/frontend/app/components/book-detail/BookDetailDescription.tsx b/frontend/app/components/book-detail/BookDetailDescription.tsx index 6cb90796..0d549258 100644 --- a/frontend/app/components/book-detail/BookDetailDescription.tsx +++ b/frontend/app/components/book-detail/BookDetailDescription.tsx @@ -1,15 +1,11 @@ -import { Text } from '@mantine/core' +import { Text } from '@mantine/core'; interface BookDetailDescriptionProps { - description: string + description: string; } const BookDetailDescription = ({ description }: BookDetailDescriptionProps) => { - return ( - - {description} - - ) -} + return {description}; +}; -export default BookDetailDescription \ No newline at end of file +export default BookDetailDescription; diff --git a/frontend/app/components/book-detail/BookDetailThumbnail.tsx b/frontend/app/components/book-detail/BookDetailThumbnail.tsx index c075f5b6..dc923a87 100644 --- a/frontend/app/components/book-detail/BookDetailThumbnail.tsx +++ b/frontend/app/components/book-detail/BookDetailThumbnail.tsx @@ -1,22 +1,20 @@ -import { AspectRatio, Image, rem } from '@mantine/core' -import NoImage from '~/img/noImage.png' +import { AspectRatio, Image, rem } from '@mantine/core'; +import NoImage from '~/img/noImage.png'; interface BookDetailThumbnailProps { - thumbnail?: string + thumbnail?: string; } const BookDetailThumbnail = ({ thumbnail }: BookDetailThumbnailProps) => { - return ( - - Book cover - - ) -} + return ( + + Book cover + + ); +}; -export default BookDetailThumbnail \ No newline at end of file +export default BookDetailThumbnail; diff --git a/frontend/app/components/book-detail/BookDetailTitle.tsx b/frontend/app/components/book-detail/BookDetailTitle.tsx index f70dc736..cd4bc1ff 100644 --- a/frontend/app/components/book-detail/BookDetailTitle.tsx +++ b/frontend/app/components/book-detail/BookDetailTitle.tsx @@ -1,13 +1,11 @@ -import { Title } from '@mantine/core' +import { Title } from '@mantine/core'; interface BookDetailTitleProps { - title: string + title: string; } const BookDetailTitle = ({ title }: BookDetailTitleProps) => { - return ( - {title} - ) -} + return {title}; +}; -export default BookDetailTitle \ No newline at end of file +export default BookDetailTitle; diff --git a/frontend/app/components/book-search/BookSearchAuthorForm.tsx b/frontend/app/components/book-search/BookSearchAuthorForm.tsx index 82075344..4809ca51 100644 --- a/frontend/app/components/book-search/BookSearchAuthorForm.tsx +++ b/frontend/app/components/book-search/BookSearchAuthorForm.tsx @@ -1,23 +1,23 @@ -import { TextInput } from "@mantine/core"; -import type { UseFormReturnType } from "@mantine/form"; -import type { GetBooksParams } from "client/client.schemas"; +import { TextInput } from '@mantine/core'; +import type { UseFormReturnType } from '@mantine/form'; +import type { GetBooksParams } from 'client/client.schemas'; interface BookSearchAuthorFormProps { - form: UseFormReturnType< - GetBooksParams, - (values: GetBooksParams) => GetBooksParams - >; + form: UseFormReturnType< + GetBooksParams, + (values: GetBooksParams) => GetBooksParams + >; } const BookSearchAuthorForm = ({ form }: BookSearchAuthorFormProps) => { - return ( - - ); + return ( + + ); }; export default BookSearchAuthorForm; diff --git a/frontend/app/components/book-search/BookSearchComponent.tsx b/frontend/app/components/book-search/BookSearchComponent.tsx index e2235712..5254f335 100644 --- a/frontend/app/components/book-search/BookSearchComponent.tsx +++ b/frontend/app/components/book-search/BookSearchComponent.tsx @@ -1,32 +1,32 @@ -import type { UseFormReturnType } from "@mantine/form"; -import type { GetBooksParams } from "client/client.schemas"; -import BookSearchForm from "./BookSearchForm"; -import BookSearchModeButton from "./BookSearchModeButton"; +import type { UseFormReturnType } from '@mantine/form'; +import type { GetBooksParams } from 'client/client.schemas'; +import BookSearchForm from './BookSearchForm'; +import BookSearchModeButton from './BookSearchModeButton'; interface BookSearchComponentProps { - isOpen: boolean; - open: () => void; - close: () => void; - form: UseFormReturnType< - GetBooksParams, - (values: GetBooksParams) => GetBooksParams - >; - handleSubmit: (props: GetBooksParams) => void; + isOpen: boolean; + open: () => void; + close: () => void; + form: UseFormReturnType< + GetBooksParams, + (values: GetBooksParams) => GetBooksParams + >; + handleSubmit: (props: GetBooksParams) => void; } const BookSearchComponent = ({ - isOpen, - open, - close, - form, - handleSubmit, + isOpen, + open, + close, + form, + handleSubmit, }: BookSearchComponentProps) => { - return ( - <> - - - - ); + return ( + <> + + + + ); }; export default BookSearchComponent; diff --git a/frontend/app/components/book-search/BookSearchForm.tsx b/frontend/app/components/book-search/BookSearchForm.tsx index 44dc3a91..56445b52 100644 --- a/frontend/app/components/book-search/BookSearchForm.tsx +++ b/frontend/app/components/book-search/BookSearchForm.tsx @@ -1,34 +1,34 @@ -import { Collapse } from "@mantine/core"; -import type { UseFormReturnType } from "@mantine/form"; -import type { GetBooksParams } from "client/client.schemas"; -import FormLayout from "../layouts/FormLayout"; -import BookSearchAuthorForm from "./BookSearchAuthorForm"; -import BookSearchIsbnForm from "./BookSearchIsbnForm"; -import BookSearchPublisherForm from "./BookSearchPublisherForm"; -import BookSearchSubmitButton from "./BookSearchSubmitButton"; -import BookSearchTitleForm from "./BookSearchTitleForm"; +import { Collapse } from '@mantine/core'; +import type { UseFormReturnType } from '@mantine/form'; +import type { GetBooksParams } from 'client/client.schemas'; +import FormLayout from '../layouts/FormLayout'; +import BookSearchAuthorForm from './BookSearchAuthorForm'; +import BookSearchIsbnForm from './BookSearchIsbnForm'; +import BookSearchPublisherForm from './BookSearchPublisherForm'; +import BookSearchSubmitButton from './BookSearchSubmitButton'; +import BookSearchTitleForm from './BookSearchTitleForm'; interface SearchFormProps { - isOpen: boolean; - form: UseFormReturnType< - GetBooksParams, - (values: GetBooksParams) => GetBooksParams - >; - handleSubmit: (props: GetBooksParams) => void; + isOpen: boolean; + form: UseFormReturnType< + GetBooksParams, + (values: GetBooksParams) => GetBooksParams + >; + handleSubmit: (props: GetBooksParams) => void; } const BookSearchForm = ({ isOpen, form, handleSubmit }: SearchFormProps) => { - return ( - - form={form} handleSubmit={handleSubmit}> - - - - - - - - ); + return ( + + form={form} handleSubmit={handleSubmit}> + + + + + + + + ); }; export default BookSearchForm; diff --git a/frontend/app/components/book-search/BookSearchIsbnForm.tsx b/frontend/app/components/book-search/BookSearchIsbnForm.tsx index 528dbf1d..184931b9 100644 --- a/frontend/app/components/book-search/BookSearchIsbnForm.tsx +++ b/frontend/app/components/book-search/BookSearchIsbnForm.tsx @@ -1,23 +1,23 @@ -import { TextInput } from "@mantine/core"; -import type { UseFormReturnType } from "@mantine/form"; -import type { GetBooksParams } from "client/client.schemas"; +import { TextInput } from '@mantine/core'; +import type { UseFormReturnType } from '@mantine/form'; +import type { GetBooksParams } from 'client/client.schemas'; interface SearchIsbnFormProps { - form: UseFormReturnType< - GetBooksParams, - (values: GetBooksParams) => GetBooksParams - >; + form: UseFormReturnType< + GetBooksParams, + (values: GetBooksParams) => GetBooksParams + >; } const BookSearchIsbnForm = ({ form }: SearchIsbnFormProps) => { - return ( - - ); + return ( + + ); }; export default BookSearchIsbnForm; diff --git a/frontend/app/components/book-search/BookSearchModeButton.tsx b/frontend/app/components/book-search/BookSearchModeButton.tsx index 089a5b56..422a4e93 100644 --- a/frontend/app/components/book-search/BookSearchModeButton.tsx +++ b/frontend/app/components/book-search/BookSearchModeButton.tsx @@ -1,14 +1,27 @@ -import { Button } from '@mantine/core' +import { Button } from '@mantine/core'; interface SearchModeButtonProps { - isOpen: boolean - open: () => void - close: () => void + isOpen: boolean; + open: () => void; + close: () => void; } -const BookSearchModeButton = ({ isOpen, open, close }: SearchModeButtonProps) => { - if (isOpen) return - return -} +const BookSearchModeButton = ({ + isOpen, + open, + close, +}: SearchModeButtonProps) => { + if (isOpen) + return ( + + ); + return ( + + ); +}; -export default BookSearchModeButton \ No newline at end of file +export default BookSearchModeButton; diff --git a/frontend/app/components/book-search/BookSearchPublisherForm.tsx b/frontend/app/components/book-search/BookSearchPublisherForm.tsx index 7f941111..da3c6f71 100644 --- a/frontend/app/components/book-search/BookSearchPublisherForm.tsx +++ b/frontend/app/components/book-search/BookSearchPublisherForm.tsx @@ -1,23 +1,23 @@ -import { TextInput } from "@mantine/core"; -import type { UseFormReturnType } from "@mantine/form"; -import type { GetBooksParams } from "client/client.schemas"; +import { TextInput } from '@mantine/core'; +import type { UseFormReturnType } from '@mantine/form'; +import type { GetBooksParams } from 'client/client.schemas'; interface SearchPublisherFormProps { - form: UseFormReturnType< - GetBooksParams, - (values: GetBooksParams) => GetBooksParams - >; + form: UseFormReturnType< + GetBooksParams, + (values: GetBooksParams) => GetBooksParams + >; } const BookSearchPublisherForm = ({ form }: SearchPublisherFormProps) => { - return ( - - ); + return ( + + ); }; export default BookSearchPublisherForm; diff --git a/frontend/app/components/book-search/BookSearchSubmitButton.tsx b/frontend/app/components/book-search/BookSearchSubmitButton.tsx index f2a0398a..16dac1e6 100644 --- a/frontend/app/components/book-search/BookSearchSubmitButton.tsx +++ b/frontend/app/components/book-search/BookSearchSubmitButton.tsx @@ -1,15 +1,12 @@ -import { Button } from '@mantine/core' -import { FaSearch } from "react-icons/fa"; +import { Button } from '@mantine/core'; +import { FaSearch } from 'react-icons/fa'; const BookSearchSubmitButton = () => { - return ( - - ) -} + return ( + + ); +}; -export default BookSearchSubmitButton \ No newline at end of file +export default BookSearchSubmitButton; diff --git a/frontend/app/components/book-search/BookSearchTitleForm.tsx b/frontend/app/components/book-search/BookSearchTitleForm.tsx index d66fcd3f..19673953 100644 --- a/frontend/app/components/book-search/BookSearchTitleForm.tsx +++ b/frontend/app/components/book-search/BookSearchTitleForm.tsx @@ -1,23 +1,23 @@ -import { TextInput } from "@mantine/core"; -import type { UseFormReturnType } from "@mantine/form"; -import type { GetBooksParams } from "client/client.schemas"; +import { TextInput } from '@mantine/core'; +import type { UseFormReturnType } from '@mantine/form'; +import type { GetBooksParams } from 'client/client.schemas'; interface SearchTitleFormProps { - form: UseFormReturnType< - GetBooksParams, - (values: GetBooksParams) => GetBooksParams - >; + form: UseFormReturnType< + GetBooksParams, + (values: GetBooksParams) => GetBooksParams + >; } const BookSearchTitleForm = ({ form }: SearchTitleFormProps) => { - return ( - - ); + return ( + + ); }; export default BookSearchTitleForm; diff --git a/frontend/app/components/books/BookCard.tsx b/frontend/app/components/books/BookCard.tsx index f5328a2b..769dd6e3 100644 --- a/frontend/app/components/books/BookCard.tsx +++ b/frontend/app/components/books/BookCard.tsx @@ -1,29 +1,29 @@ -import { Card } from "@mantine/core"; -import type { Book } from "client/client.schemas"; -import { useAtom } from "jotai"; -import { userAtom } from "~/stores/userAtom"; -import BookCardFooter from "./BookCardFooter"; -import BookCardHeader from "./BookCardHeader"; -import BookCardThumbnail from "./BookCardThumbnail"; +import { Card } from '@mantine/core'; +import type { Book } from 'client/client.schemas'; +import { useAtom } from 'jotai'; +import { userAtom } from '~/stores/userAtom'; +import BookCardFooter from './BookCardFooter'; +import BookCardHeader from './BookCardHeader'; +import BookCardThumbnail from './BookCardThumbnail'; interface BookCardProps { - book: Book; + book: Book; } const BookCard = ({ book }: BookCardProps) => { - const [user] = useAtom(userAtom); - return ( - - - - - - - + const [user] = useAtom(userAtom); + return ( + + + + + + + - {!!user && } - - ); + {!!user && } + + ); }; export default BookCard; diff --git a/frontend/app/components/books/BookCardCartButton.tsx b/frontend/app/components/books/BookCardCartButton.tsx index 9f0d2a7e..5beb1cb3 100644 --- a/frontend/app/components/books/BookCardCartButton.tsx +++ b/frontend/app/components/books/BookCardCartButton.tsx @@ -1,31 +1,31 @@ -import { Button } from "@mantine/core"; -import { useAtom } from "jotai"; -import { BiSolidCartAdd } from "react-icons/bi"; -import { cartAtom } from "~/stores/cartAtom"; +import { Button } from '@mantine/core'; +import { useAtom } from 'jotai'; +import { BiSolidCartAdd } from 'react-icons/bi'; +import { cartAtom } from '~/stores/cartAtom'; interface BookCardCartButtonProps { - id: number; - stock: number; + id: number; + stock: number; } const BookCardCartButton = ({ id, stock }: BookCardCartButtonProps) => { - const [cart, setCart] = useAtom(cartAtom); - const addCart = () => { - setCart([...cart, { id, stock }]); - }; - return ( - - ); + const [cart, setCart] = useAtom(cartAtom); + const addCart = () => { + setCart([...cart, { id, stock }]); + }; + return ( + + ); }; export default BookCardCartButton; diff --git a/frontend/app/components/books/BookCardFooter.tsx b/frontend/app/components/books/BookCardFooter.tsx index 5a8305c3..dc6753c3 100644 --- a/frontend/app/components/books/BookCardFooter.tsx +++ b/frontend/app/components/books/BookCardFooter.tsx @@ -1,19 +1,17 @@ -import { Center } from '@mantine/core' -import BookCardCartButton from './BookCardCartButton' +import { Center } from '@mantine/core'; +import BookCardCartButton from './BookCardCartButton'; interface BookCardFooterProps { - id: number - stock: number + id: number; + stock: number; } const BookCardFooter = ({ id, stock }: BookCardFooterProps) => { - return ( -
- -
- ) -} + return ( +
+ +
+ ); +}; -export default BookCardFooter \ No newline at end of file +export default BookCardFooter; diff --git a/frontend/app/components/books/BookCardHeader.tsx b/frontend/app/components/books/BookCardHeader.tsx index 54bdb2bb..cbaa332c 100644 --- a/frontend/app/components/books/BookCardHeader.tsx +++ b/frontend/app/components/books/BookCardHeader.tsx @@ -1,37 +1,43 @@ -import { Checkbox, Group } from '@mantine/core' -import { selectedBooksAtom } from '~/stores/cartAtom' -import { useAtom } from 'jotai' -import { userAtom } from '~/stores/userAtom' -import type { CartProps } from '~/stores/cartAtom' -import BookCardHeaderBadge from './BookCardHeaderBadge' +import { Checkbox, Group } from '@mantine/core'; +import { selectedBooksAtom } from '~/stores/cartAtom'; +import { useAtom } from 'jotai'; +import { userAtom } from '~/stores/userAtom'; +import type { CartProps } from '~/stores/cartAtom'; +import BookCardHeaderBadge from './BookCardHeaderBadge'; interface BookCardHeaderProps { - id: number - stock: number + id: number; + stock: number; } const BookCardHeader = ({ id, stock }: BookCardHeaderProps) => { - const [selectedBook, setSelectedBook] = useAtom(selectedBooksAtom) - const [user,] = useAtom(userAtom) - // この関数は、選択されている本のIDと表示する本のIDを比較します。 - const selectedCheck = (element: CartProps) => element.id === id + const [selectedBook, setSelectedBook] = useAtom(selectedBooksAtom); + const [user] = useAtom(userAtom); + // この関数は、選択されている本のIDと表示する本のIDを比較します。 + const selectedCheck = (element: CartProps) => element.id === id; - // チェックボックスの状態が変化した時に、すでに選択されている本の配列に含まれている場合、選択を外し、 - // 選択されていなかった場合は、選択します。 - const selectedBookAdd = () => { - if (selectedBook.some(selectedCheck)) { - setSelectedBook(selectedBook.filter((element) => element.id !== id)) - } else { - setSelectedBook([...selectedBook, { id, stock }]) - } - } + // チェックボックスの状態が変化した時に、すでに選択されている本の配列に含まれている場合、選択を外し、 + // 選択されていなかった場合は、選択します。 + const selectedBookAdd = () => { + if (selectedBook.some(selectedCheck)) { + setSelectedBook(selectedBook.filter((element) => element.id !== id)); + } else { + setSelectedBook([...selectedBook, { id, stock }]); + } + }; - return ( - - {!!user && } - - - ) -} + return ( + + {!!user && ( + + )} + + + ); +}; -export default BookCardHeader \ No newline at end of file +export default BookCardHeader; diff --git a/frontend/app/components/books/BookCardHeaderBadge.tsx b/frontend/app/components/books/BookCardHeaderBadge.tsx index 75c0a9c7..0d985246 100644 --- a/frontend/app/components/books/BookCardHeaderBadge.tsx +++ b/frontend/app/components/books/BookCardHeaderBadge.tsx @@ -1,12 +1,22 @@ -import { Badge } from '@mantine/core' +import { Badge } from '@mantine/core'; interface BookCardHeaderBadgeProps { - stock: number + stock: number; } const BookCardHeaderBadge = ({ stock }: BookCardHeaderBadgeProps) => { - if (stock > 0) return 貸出可 - else return 貸出不可 -} + if (stock > 0) + return ( + + 貸出可 + + ); + else + return ( + + 貸出不可 + + ); +}; -export default BookCardHeaderBadge \ No newline at end of file +export default BookCardHeaderBadge; diff --git a/frontend/app/components/books/BookCardThumbnail.tsx b/frontend/app/components/books/BookCardThumbnail.tsx index 9a30726c..eb434589 100644 --- a/frontend/app/components/books/BookCardThumbnail.tsx +++ b/frontend/app/components/books/BookCardThumbnail.tsx @@ -1,26 +1,24 @@ -import { AspectRatio, Image, rem } from '@mantine/core' -import { useNavigate } from '@remix-run/react' -import NoImage from '~/img/noImage.png' +import { AspectRatio, Image, rem } from '@mantine/core'; +import { useNavigate } from '@remix-run/react'; +import NoImage from '~/img/noImage.png'; interface BookCardThumbnailProps { - id: number - thumbnail?: string + id: number; + thumbnail?: string; } const BookCardThumbnail = ({ id, thumbnail }: BookCardThumbnailProps) => { - const navigate = useNavigate() - return ( - navigate(`books/${id}`)} - > - Book cover - - ) -} + const navigate = useNavigate(); + return ( + navigate(`books/${id}`)} + > + Book cover + + ); +}; -export default BookCardThumbnail \ No newline at end of file +export default BookCardThumbnail; diff --git a/frontend/app/components/books/BookCards.tsx b/frontend/app/components/books/BookCards.tsx index d0e84a48..2f4262a4 100644 --- a/frontend/app/components/books/BookCards.tsx +++ b/frontend/app/components/books/BookCards.tsx @@ -1,42 +1,42 @@ -import { ScrollArea, SimpleGrid } from "@mantine/core"; -import { Book } from "client/client.schemas"; -import { useAtom } from "jotai"; -import { userAtom } from "~/stores/userAtom"; -import BookCard from "./BookCard"; -import BookSelectedDialog from "./BookSelectedDialog"; -import NoBookComponent from "./NoBookComponent"; +import { ScrollArea, SimpleGrid } from '@mantine/core'; +import { Book } from 'client/client.schemas'; +import { useAtom } from 'jotai'; +import { userAtom } from '~/stores/userAtom'; +import BookCard from './BookCard'; +import BookSelectedDialog from './BookSelectedDialog'; +import NoBookComponent from './NoBookComponent'; interface BookCardsProps { - books: Book[]; + books: Book[]; } const BookCards = ({ books }: BookCardsProps) => { - const [user] = useAtom(userAtom); - if (books.length === 0) return ; + const [user] = useAtom(userAtom); + if (books.length === 0) return ; - return ( - <> - - - {books.map((book) => ( - - ))} - - - {!!user && } - - ); + return ( + <> + + + {books.map((book) => ( + + ))} + + + {!!user && } + + ); }; export default BookCards; diff --git a/frontend/app/components/books/BookListComponent.tsx b/frontend/app/components/books/BookListComponent.tsx index 37f4e861..8283b1ca 100644 --- a/frontend/app/components/books/BookListComponent.tsx +++ b/frontend/app/components/books/BookListComponent.tsx @@ -1,71 +1,71 @@ -import { Stack } from "@mantine/core"; -import type { UseFormReturnType } from "@mantine/form"; -import { getBooksResponse } from "client/client"; -import type { GetBooksParams } from "client/client.schemas"; -import BookSearchComponent from "../book-search/BookSearchComponent"; -import ContentsHeader from "../common/ContentsHeader"; -import ErrorComponent from "../common/ErrorComponent"; -import PaginationComponent from "../common/PaginationComponent"; -import BookCards from "./BookCards"; +import { Stack } from '@mantine/core'; +import type { UseFormReturnType } from '@mantine/form'; +import { getBooksResponse } from 'client/client'; +import type { GetBooksParams } from 'client/client.schemas'; +import BookSearchComponent from '../book-search/BookSearchComponent'; +import ContentsHeader from '../common/ContentsHeader'; +import ErrorComponent from '../common/ErrorComponent'; +import PaginationComponent from '../common/PaginationComponent'; +import BookCards from './BookCards'; interface BookListComponentProps { - booksResponse: getBooksResponse; - form: UseFormReturnType< - GetBooksParams, - (values: GetBooksParams) => GetBooksParams - >; - handleSubmit: (props: GetBooksParams) => void; - isOpen: boolean; - open: () => void; - close: () => void; - handlePaginationChange: (newPage: number) => void; - handleLimitChange: (newLimit: number) => void; - page?: number; - limit?: number; - totalBook: number; + booksResponse: getBooksResponse; + form: UseFormReturnType< + GetBooksParams, + (values: GetBooksParams) => GetBooksParams + >; + handleSubmit: (props: GetBooksParams) => void; + isOpen: boolean; + open: () => void; + close: () => void; + handlePaginationChange: (newPage: number) => void; + handleLimitChange: (newLimit: number) => void; + page?: number; + limit?: number; + totalBook: number; } const BookListComponent = ({ - booksResponse, - form, - handleSubmit, - isOpen, - open, - close, - handlePaginationChange, - handleLimitChange, - page, - limit, - totalBook, + booksResponse, + form, + handleSubmit, + isOpen, + open, + close, + handlePaginationChange, + handleLimitChange, + page, + limit, + totalBook, }: BookListComponentProps) => { - return ( - - - - {booksResponse.status !== 200 ? ( - - ) : ( - - )} - - - ); + return ( + + + + {booksResponse.status !== 200 ? ( + + ) : ( + + )} + + + ); }; export default BookListComponent; diff --git a/frontend/app/components/books/BookSelectedDialog.tsx b/frontend/app/components/books/BookSelectedDialog.tsx index 628266d0..ff848187 100644 --- a/frontend/app/components/books/BookSelectedDialog.tsx +++ b/frontend/app/components/books/BookSelectedDialog.tsx @@ -1,40 +1,40 @@ -import { Button, Center, Dialog, Stack, Text } from "@mantine/core"; -import { useAtom } from "jotai"; -import { selectedBooksAtom } from "~/stores/cartAtom"; +import { Button, Center, Dialog, Stack, Text } from '@mantine/core'; +import { useAtom } from 'jotai'; +import { selectedBooksAtom } from '~/stores/cartAtom'; const BookSelectedDialog = () => { - const [selectedBook, setSelectedBook] = useAtom(selectedBooksAtom); - return ( - 0} - onClose={() => setSelectedBook([])} - > - -
- 選択中の本が{selectedBook.length}冊あります -
- - - -
-
- ); + const [selectedBook, setSelectedBook] = useAtom(selectedBooksAtom); + return ( + 0} + onClose={() => setSelectedBook([])} + > + +
+ 選択中の本が{selectedBook.length}冊あります +
+ + + +
+
+ ); }; export default BookSelectedDialog; diff --git a/frontend/app/components/books/NoBookComponent.tsx b/frontend/app/components/books/NoBookComponent.tsx index 375ad11d..afb08b07 100644 --- a/frontend/app/components/books/NoBookComponent.tsx +++ b/frontend/app/components/books/NoBookComponent.tsx @@ -1,14 +1,14 @@ -import { Blockquote, Center } from '@mantine/core' -import { FaInfoCircle } from "react-icons/fa"; +import { Blockquote, Center } from '@mantine/core'; +import { FaInfoCircle } from 'react-icons/fa'; const NoBookComponent = () => { - return ( -
-
} mt="xl"> - 本が見つかりませんでした。 -
-
- ) -} + return ( +
+
} mt="xl"> + 本が見つかりませんでした。 +
+
+ ); +}; -export default NoBookComponent \ No newline at end of file +export default NoBookComponent; diff --git a/frontend/app/components/common/ContentsHeader.tsx b/frontend/app/components/common/ContentsHeader.tsx index 408de127..e600b1cf 100644 --- a/frontend/app/components/common/ContentsHeader.tsx +++ b/frontend/app/components/common/ContentsHeader.tsx @@ -1,33 +1,31 @@ -import { Group } from '@mantine/core' -import LimitSelect from './LimitSelect' -import CurrentContentNumber from './CurrentContentNumber' +import { Group } from '@mantine/core'; +import LimitSelect from './LimitSelect'; +import CurrentContentNumber from './CurrentContentNumber'; interface ContentsHeaderProps { - page?: number, - limit?: number, - total: number, - handleLimitChange: (newLimit: number) => void + page?: number; + limit?: number; + total: number; + handleLimitChange: (newLimit: number) => void; } const ContentsHeader = ({ - page, - limit, - total, - handleLimitChange + page, + limit, + total, + handleLimitChange, }: ContentsHeaderProps) => { - const truePage = page ?? 1 - const trueLimit = limit ?? 10 - const start = (truePage - 1) * trueLimit + 1 - const stop = truePage * trueLimit + const truePage = page ?? 1; + const trueLimit = limit ?? 10; + const start = (truePage - 1) * trueLimit + 1; + const stop = truePage * trueLimit; - return ( - - - - - ) -} + return ( + + + + + ); +}; -export default ContentsHeader \ No newline at end of file +export default ContentsHeader; diff --git a/frontend/app/components/common/CurrentContentNumber.tsx b/frontend/app/components/common/CurrentContentNumber.tsx index 16811463..42abc66e 100644 --- a/frontend/app/components/common/CurrentContentNumber.tsx +++ b/frontend/app/components/common/CurrentContentNumber.tsx @@ -1,18 +1,22 @@ -import { Text } from '@mantine/core' +import { Text } from '@mantine/core'; interface CurrentContentNumberProps { - start: number, - stop: number, - total: number + start: number; + stop: number; + total: number; } -const CurrentContentNumber = ({ start, stop, total }: CurrentContentNumberProps) => { - const trueStop = stop < total ? stop : total - return ( - - {total > 1 ? `${start} ~ ${trueStop} 件` : `${total} 件`} (全 {total}件) - - ) -} +const CurrentContentNumber = ({ + start, + stop, + total, +}: CurrentContentNumberProps) => { + const trueStop = stop < total ? stop : total; + return ( + + {total > 1 ? `${start} ~ ${trueStop} 件` : `${total} 件`} (全 {total}件) + + ); +}; -export default CurrentContentNumber \ No newline at end of file +export default CurrentContentNumber; diff --git a/frontend/app/components/common/ErrorComponent.tsx b/frontend/app/components/common/ErrorComponent.tsx index 1b13e688..d0a45daa 100644 --- a/frontend/app/components/common/ErrorComponent.tsx +++ b/frontend/app/components/common/ErrorComponent.tsx @@ -1,19 +1,18 @@ -import { Blockquote, Center } from '@mantine/core' -import { MdError } from "react-icons/md"; +import { Blockquote, Center } from '@mantine/core'; +import { MdError } from 'react-icons/md'; interface ErrorComponentProps { - message: string + message: string; } - const ErrorComponent = ({ message }: ErrorComponentProps) => { - return ( -
-
} mt="xl"> - {message} -
-
- ) -} + return ( +
+
} mt="xl"> + {message} +
+
+ ); +}; -export default ErrorComponent \ No newline at end of file +export default ErrorComponent; diff --git a/frontend/app/components/common/LimitSelect.tsx b/frontend/app/components/common/LimitSelect.tsx index ca1bdf04..bb484a38 100644 --- a/frontend/app/components/common/LimitSelect.tsx +++ b/frontend/app/components/common/LimitSelect.tsx @@ -1,19 +1,19 @@ -import { NativeSelect } from '@mantine/core' +import { NativeSelect } from '@mantine/core'; interface LimitSelectProps { - value?: number - handleLimitChange: (newLimit: number) => void + value?: number; + handleLimitChange: (newLimit: number) => void; } const LimitSelect = ({ value, handleLimitChange }: LimitSelectProps) => { - return ( - handleLimitChange(Number(event.currentTarget.value)))} - /> - ) -} + return ( + handleLimitChange(Number(event.currentTarget.value))} + /> + ); +}; -export default LimitSelect \ No newline at end of file +export default LimitSelect; diff --git a/frontend/app/components/common/PaginationComponent.tsx b/frontend/app/components/common/PaginationComponent.tsx index 48f267b8..344f6e9d 100644 --- a/frontend/app/components/common/PaginationComponent.tsx +++ b/frontend/app/components/common/PaginationComponent.tsx @@ -1,30 +1,30 @@ -import { Center, Pagination } from '@mantine/core' +import { Center, Pagination } from '@mantine/core'; interface PaginationComponentProps { - totalNum: number - page?: number - limit?: number - handlePaginationChange: (newPage: number) => void + totalNum: number; + page?: number; + limit?: number; + handlePaginationChange: (newPage: number) => void; } const PaginationComponent = ({ - totalNum, - page, - limit, - handlePaginationChange + totalNum, + page, + limit, + handlePaginationChange, }: PaginationComponentProps) => { - const limitNum = limit ?? 10 - const totalPage = (totalNum / limitNum) + 1 - return ( -
- -
- ) -} + const limitNum = limit ?? 10; + const totalPage = totalNum / limitNum + 1; + return ( +
+ +
+ ); +}; -export default PaginationComponent \ No newline at end of file +export default PaginationComponent; diff --git a/frontend/app/components/header/HeaderBookMenu.tsx b/frontend/app/components/header/HeaderBookMenu.tsx index 579b20da..8ecd8776 100644 --- a/frontend/app/components/header/HeaderBookMenu.tsx +++ b/frontend/app/components/header/HeaderBookMenu.tsx @@ -1,32 +1,39 @@ -import { Button, Menu } from "@mantine/core" -import { useNavigate } from "@remix-run/react"; -import { FaBook } from "react-icons/fa"; -import { LuBookCopy } from "react-icons/lu"; -import { BiSolidBookAdd } from "react-icons/bi"; -import { userAtom } from "~/stores/userAtom"; -import { useAtom } from "jotai"; +import { Button, Menu } from '@mantine/core'; +import { useNavigate } from '@remix-run/react'; +import { FaBook } from 'react-icons/fa'; +import { LuBookCopy } from 'react-icons/lu'; +import { BiSolidBookAdd } from 'react-icons/bi'; +import { userAtom } from '~/stores/userAtom'; +import { useAtom } from 'jotai'; const HeaderBookMenu = () => { - const navigate = useNavigate() - const [user,] = useAtom(userAtom) - return ( - - - - - - } onClick={() => navigate('/home')}> - 書籍一覧 - - {!!user && } onClick={() => navigate('/home/books/new')}> - 書籍追加 - } + const navigate = useNavigate(); + const [user] = useAtom(userAtom); + return ( + + + + + + } + onClick={() => navigate('/home')} + > + 書籍一覧 + + {!!user && ( + } + onClick={() => navigate('/home/books/new')} + > + 書籍追加 + + )} + + + ); +}; - - - ) -} - -export default HeaderBookMenu \ No newline at end of file +export default HeaderBookMenu; diff --git a/frontend/app/components/header/HeaderComponent.tsx b/frontend/app/components/header/HeaderComponent.tsx index 593679ef..d18aea23 100644 --- a/frontend/app/components/header/HeaderComponent.tsx +++ b/frontend/app/components/header/HeaderComponent.tsx @@ -1,40 +1,40 @@ -import { AppShell, Group } from "@mantine/core"; -import { getUser } from "client/client"; -import { User } from "client/client.schemas"; -import { useAtom } from "jotai"; -import { userAtom } from "~/stores/userAtom"; -import HeaderMainComponent from "./HeaderMainComponent"; -import HeaderTitleLogo from "./HeaderTitleLogo"; +import { AppShell, Group } from '@mantine/core'; +import { getUser } from 'client/client'; +import { User } from 'client/client.schemas'; +import { useAtom } from 'jotai'; +import { userAtom } from '~/stores/userAtom'; +import HeaderMainComponent from './HeaderMainComponent'; +import HeaderTitleLogo from './HeaderTitleLogo'; const getCookieUserId = () => { - if (typeof document === "undefined") return undefined; - return document.cookie - .split("; ") - .find((row) => row.startsWith("__Secure-user_id=")) - ?.split("=")[1]; + if (typeof document === 'undefined') return undefined; + return document.cookie + .split('; ') + .find((row) => row.startsWith('__Secure-user_id=')) + ?.split('=')[1]; }; const HeaderComponent = () => { - const [user, setUser] = useAtom(userAtom); - const userId = getCookieUserId(); - if (userId) { - if (!user) { - // ユーザ情報を取得するAPIを呼び出す。 - getUser(userId).then((response) => { - if (response.status === 200) { - setUser(response.data as User); - } - }); - } - } - return ( - - - - - - - ); + const [user, setUser] = useAtom(userAtom); + const userId = getCookieUserId(); + if (userId) { + if (!user) { + // ユーザ情報を取得するAPIを呼び出す。 + getUser(userId).then((response) => { + if (response.status === 200) { + setUser(response.data as User); + } + }); + } + } + return ( + + + + + + + ); }; export default HeaderComponent; diff --git a/frontend/app/components/header/HeaderLoginButton.tsx b/frontend/app/components/header/HeaderLoginButton.tsx index e44e930e..12fa90e0 100644 --- a/frontend/app/components/header/HeaderLoginButton.tsx +++ b/frontend/app/components/header/HeaderLoginButton.tsx @@ -1,14 +1,18 @@ -import { Button } from '@mantine/core' -import { useNavigate } from '@remix-run/react' -import { LuLogIn } from 'react-icons/lu' +import { Button } from '@mantine/core'; +import { useNavigate } from '@remix-run/react'; +import { LuLogIn } from 'react-icons/lu'; const HeaderLoginButton = () => { - const navigate = useNavigate() - return ( - - ) -} + const navigate = useNavigate(); + return ( + + ); +}; -export default HeaderLoginButton \ No newline at end of file +export default HeaderLoginButton; diff --git a/frontend/app/components/header/HeaderLoginComponent.tsx b/frontend/app/components/header/HeaderLoginComponent.tsx index a6ca5430..56373eb8 100644 --- a/frontend/app/components/header/HeaderLoginComponent.tsx +++ b/frontend/app/components/header/HeaderLoginComponent.tsx @@ -1,67 +1,67 @@ -import { Button, Group, Modal, Stack, Text } from "@mantine/core"; -import { useDisclosure } from "@mantine/hooks"; -import { useNavigate } from "@remix-run/react"; -import { useLogout } from "client/client"; -import { useAtom } from "jotai"; -import { LuLogOut } from "react-icons/lu"; -import { userAtom } from "~/stores/userAtom"; -import { errorNotifications, successNotifications } from "~/utils/notification"; -import HeaderBookMenu from "./HeaderBookMenu"; -import HeaderUserMenu from "./HeaderUserMenu"; -import HeaderUsersMenu from "./HeaderUsersMenu"; +import { Button, Group, Modal, Stack, Text } from '@mantine/core'; +import { useDisclosure } from '@mantine/hooks'; +import { useNavigate } from '@remix-run/react'; +import { useLogout } from 'client/client'; +import { useAtom } from 'jotai'; +import { LuLogOut } from 'react-icons/lu'; +import { userAtom } from '~/stores/userAtom'; +import { errorNotifications, successNotifications } from '~/utils/notification'; +import HeaderBookMenu from './HeaderBookMenu'; +import HeaderUserMenu from './HeaderUserMenu'; +import HeaderUsersMenu from './HeaderUsersMenu'; const HeaderLoginComponent = () => { - const [, setUser] = useAtom(userAtom); - const [opened, { open, close }] = useDisclosure(); - const navigate = useNavigate(); - const logoutTask = useLogout(); - const handleLogout = () => { - logoutTask.mutate(undefined, { - onSuccess: (response) => { - switch (response.status) { - case 204: - setUser(undefined); - successNotifications("ログアウトしました"); - navigate("/home"); - break; - case 500: - errorNotifications("サーバーエラーが発生しました"); - break; - default: - errorNotifications("エラーが発生しました"); - break; - } - }, - onError: () => { - errorNotifications("ログアウトに失敗しました"); - close(); - }, - }); - }; - return ( - <> - - - - - - - - - ログアウトしますか? - - - - - - - - - ); + const [, setUser] = useAtom(userAtom); + const [opened, { open, close }] = useDisclosure(); + const navigate = useNavigate(); + const logoutTask = useLogout(); + const handleLogout = () => { + logoutTask.mutate(undefined, { + onSuccess: (response) => { + switch (response.status) { + case 204: + setUser(undefined); + successNotifications('ログアウトしました'); + navigate('/home'); + break; + case 500: + errorNotifications('サーバーエラーが発生しました'); + break; + default: + errorNotifications('エラーが発生しました'); + break; + } + }, + onError: () => { + errorNotifications('ログアウトに失敗しました'); + close(); + }, + }); + }; + return ( + <> + + + + + + + + + ログアウトしますか? + + + + + + + + + ); }; export default HeaderLoginComponent; diff --git a/frontend/app/components/header/HeaderLogoutComponent.tsx b/frontend/app/components/header/HeaderLogoutComponent.tsx index 6c1a8c4b..42771b8d 100644 --- a/frontend/app/components/header/HeaderLogoutComponent.tsx +++ b/frontend/app/components/header/HeaderLogoutComponent.tsx @@ -1,14 +1,14 @@ -import { Group } from "@mantine/core" -import HeaderBookMenu from "./HeaderBookMenu" -import HeaderLoginButton from "./HeaderLoginButton" +import { Group } from '@mantine/core'; +import HeaderBookMenu from './HeaderBookMenu'; +import HeaderLoginButton from './HeaderLoginButton'; const HeaderLogoutComponent = () => { - return ( - - - - - ) -} + return ( + + + + + ); +}; -export default HeaderLogoutComponent \ No newline at end of file +export default HeaderLogoutComponent; diff --git a/frontend/app/components/header/HeaderMainComponent.tsx b/frontend/app/components/header/HeaderMainComponent.tsx index 171f0e01..3129d3f9 100644 --- a/frontend/app/components/header/HeaderMainComponent.tsx +++ b/frontend/app/components/header/HeaderMainComponent.tsx @@ -1,12 +1,12 @@ -import HeaderLoginComponent from './HeaderLoginComponent' -import HeaderLogoutComponent from './HeaderLogoutComponent' -import { useAtom } from "jotai" -import { userAtom } from "~/stores/userAtom" +import HeaderLoginComponent from './HeaderLoginComponent'; +import HeaderLogoutComponent from './HeaderLogoutComponent'; +import { useAtom } from 'jotai'; +import { userAtom } from '~/stores/userAtom'; const HeaderMainComponent = () => { - const [user,] = useAtom(userAtom) + const [user] = useAtom(userAtom); - return <>{!user ? : } -} + return <>{!user ? : }; +}; -export default HeaderMainComponent \ No newline at end of file +export default HeaderMainComponent; diff --git a/frontend/app/components/header/HeaderTitleLogo.tsx b/frontend/app/components/header/HeaderTitleLogo.tsx index bbaee3e9..e65b0157 100644 --- a/frontend/app/components/header/HeaderTitleLogo.tsx +++ b/frontend/app/components/header/HeaderTitleLogo.tsx @@ -1,20 +1,14 @@ -import { AspectRatio, Image, rem } from '@mantine/core' -import Logo from '~/img/kitcc.png' +import { AspectRatio, Image, rem } from '@mantine/core'; +import Logo from '~/img/kitcc.png'; const HeaderTitleLogo = () => { - return ( - - - kitcc-logo - - - ) -} + return ( + + + kitcc-logo + + + ); +}; -export default HeaderTitleLogo \ No newline at end of file +export default HeaderTitleLogo; diff --git a/frontend/app/components/header/HeaderUserMenu.tsx b/frontend/app/components/header/HeaderUserMenu.tsx index 91692ff3..24fa665c 100644 --- a/frontend/app/components/header/HeaderUserMenu.tsx +++ b/frontend/app/components/header/HeaderUserMenu.tsx @@ -1,37 +1,43 @@ -import { Button, Menu } from '@mantine/core' -import { FaUserCircle, FaUser } from "react-icons/fa"; -import { LuLogOut, LuShoppingCart } from "react-icons/lu"; +import { Button, Menu } from '@mantine/core'; +import { FaUserCircle, FaUser } from 'react-icons/fa'; +import { LuLogOut, LuShoppingCart } from 'react-icons/lu'; import { userAtom } from '~/stores/userAtom'; import { useAtom } from 'jotai'; import { useNavigate } from '@remix-run/react'; interface HeaderUserMenuProps { - open: () => void + open: () => void; } const HeaderUserMenu = ({ open }: HeaderUserMenuProps) => { - const [user,] = useAtom(userAtom) - const navigate = useNavigate() - return ( - - - - - - } onClick={() => navigate('/home/mypage')} > - マイページ - - } onClick={() => navigate('/home/cart')} > - カート - - } onClick={() => open()}> - ログアウト - - - - ) -} + const [user] = useAtom(userAtom); + const navigate = useNavigate(); + return ( + + + + + + } + onClick={() => navigate('/home/mypage')} + > + マイページ + + } + onClick={() => navigate('/home/cart')} + > + カート + + } onClick={() => open()}> + ログアウト + + + + ); +}; -export default HeaderUserMenu \ No newline at end of file +export default HeaderUserMenu; diff --git a/frontend/app/components/header/HeaderUsersMenu.tsx b/frontend/app/components/header/HeaderUsersMenu.tsx index 82e8b41a..7ee62cc5 100644 --- a/frontend/app/components/header/HeaderUsersMenu.tsx +++ b/frontend/app/components/header/HeaderUsersMenu.tsx @@ -1,27 +1,33 @@ -import { Button, Menu } from '@mantine/core' -import { FaUsers, FaUserFriends } from "react-icons/fa"; -import { FaUserPlus } from "react-icons/fa6"; +import { Button, Menu } from '@mantine/core'; +import { FaUsers, FaUserFriends } from 'react-icons/fa'; +import { FaUserPlus } from 'react-icons/fa6'; import { useNavigate } from '@remix-run/react'; const HeaderUsersMenu = () => { - const navigate = useNavigate() - return ( - - - - - - } onClick={() => navigate('/home/users')}> - ユーザー一覧 - - } onClick={() => navigate('/home/user-add')}> - ユーザー追加 - - - - ) -} + const navigate = useNavigate(); + return ( + + + + + + } + onClick={() => navigate('/home/users')} + > + ユーザー一覧 + + } + onClick={() => navigate('/home/user-add')} + > + ユーザー追加 + + + + ); +}; -export default HeaderUsersMenu \ No newline at end of file +export default HeaderUsersMenu; diff --git a/frontend/app/components/layouts/FormBaseLayout.tsx b/frontend/app/components/layouts/FormBaseLayout.tsx index 2d30b9df..fb4dd5d4 100644 --- a/frontend/app/components/layouts/FormBaseLayout.tsx +++ b/frontend/app/components/layouts/FormBaseLayout.tsx @@ -1,25 +1,18 @@ -import React from 'react' -import { Center, Paper } from '@mantine/core' +import React from 'react'; +import { Center, Paper } from '@mantine/core'; interface FormBaseLayoutProps { - children: React.ReactNode + children: React.ReactNode; } const FormBaseLayout = ({ children }: FormBaseLayoutProps) => { - return ( -
- - {children} - -
- ) -} + return ( +
+ + {children} + +
+ ); +}; -export default FormBaseLayout \ No newline at end of file +export default FormBaseLayout; diff --git a/frontend/app/components/layouts/FormLayout.tsx b/frontend/app/components/layouts/FormLayout.tsx index 90916c26..6d84e2d8 100644 --- a/frontend/app/components/layouts/FormLayout.tsx +++ b/frontend/app/components/layouts/FormLayout.tsx @@ -1,25 +1,25 @@ -import { Stack } from "@mantine/core"; -import type { UseFormReturnType } from "@mantine/form"; -import React from "react"; +import { Stack } from '@mantine/core'; +import type { UseFormReturnType } from '@mantine/form'; +import React from 'react'; interface FormLayoutProps { - form: UseFormReturnType T>; - handleSubmit: (props: T) => void; - children: React.ReactNode; + form: UseFormReturnType T>; + handleSubmit: (props: T) => void; + children: React.ReactNode; } const FormLayout = ({ - form, - handleSubmit, - children, + form, + handleSubmit, + children, }: FormLayoutProps) => { - return ( -
handleSubmit(values))}> - - {children} - -
- ); + return ( +
handleSubmit(values))}> + + {children} + +
+ ); }; export default FormLayout; diff --git a/frontend/app/components/login/LoginEmailForm.tsx b/frontend/app/components/login/LoginEmailForm.tsx index c57f5f9f..5cee15f0 100644 --- a/frontend/app/components/login/LoginEmailForm.tsx +++ b/frontend/app/components/login/LoginEmailForm.tsx @@ -1,22 +1,22 @@ -import { TextInput } from "@mantine/core"; -import type { UseFormReturnType } from "@mantine/form"; -import type { LoginBody } from "client/client.schemas"; +import { TextInput } from '@mantine/core'; +import type { UseFormReturnType } from '@mantine/form'; +import type { LoginBody } from 'client/client.schemas'; interface LoginEmailFormProps { - form: UseFormReturnType LoginBody>; + form: UseFormReturnType LoginBody>; } const LoginEmailForm = ({ form }: LoginEmailFormProps) => { - return ( - - ); + return ( + + ); }; export default LoginEmailForm; diff --git a/frontend/app/components/login/LoginFormComponent.tsx b/frontend/app/components/login/LoginFormComponent.tsx index e5ac8ec6..8052dc0e 100644 --- a/frontend/app/components/login/LoginFormComponent.tsx +++ b/frontend/app/components/login/LoginFormComponent.tsx @@ -1,35 +1,35 @@ -import type { UseFormReturnType } from "@mantine/form"; -import type { LoginBody } from "client/client.schemas"; -import FormBaseLayout from "../layouts/FormBaseLayout"; -import FormLayout from "../layouts/FormLayout"; -import LoginEmailForm from "./LoginEmailForm"; -import LoginFormHelpText from "./LoginFormHelpText"; -import LoginFormTitle from "./LoginFormTitle"; -import LoginPasswordForm from "./LoginPasswordForm"; -import LoginSubmitButton from "./LoginSubmitButton"; +import type { UseFormReturnType } from '@mantine/form'; +import type { LoginBody } from 'client/client.schemas'; +import FormBaseLayout from '../layouts/FormBaseLayout'; +import FormLayout from '../layouts/FormLayout'; +import LoginEmailForm from './LoginEmailForm'; +import LoginFormHelpText from './LoginFormHelpText'; +import LoginFormTitle from './LoginFormTitle'; +import LoginPasswordForm from './LoginPasswordForm'; +import LoginSubmitButton from './LoginSubmitButton'; interface LoginFormComponentProps { - isPending: boolean; - form: UseFormReturnType LoginBody>; - handleSubmit: (props: LoginBody) => void; + isPending: boolean; + form: UseFormReturnType LoginBody>; + handleSubmit: (props: LoginBody) => void; } const LoginFormComponent = ({ - isPending, - form, - handleSubmit, + isPending, + form, + handleSubmit, }: LoginFormComponentProps) => { - return ( - - form={form} handleSubmit={handleSubmit}> - - - - - - - - ); + return ( + + form={form} handleSubmit={handleSubmit}> + + + + + + + + ); }; export default LoginFormComponent; diff --git a/frontend/app/components/login/LoginFormHelpText.tsx b/frontend/app/components/login/LoginFormHelpText.tsx index 6a368be4..4e304e3e 100644 --- a/frontend/app/components/login/LoginFormHelpText.tsx +++ b/frontend/app/components/login/LoginFormHelpText.tsx @@ -1,14 +1,13 @@ -import { Text } from '@mantine/core' +import { Text } from '@mantine/core'; const LoginFormHelpText = () => { - return ( - - アカウントが無い場合、またはパスワードを忘れた場合は、
管理者にお問い合わせください。 -
- ) -} + return ( + + アカウントが無い場合、またはパスワードを忘れた場合は、 +
+ 管理者にお問い合わせください。 +
+ ); +}; -export default LoginFormHelpText \ No newline at end of file +export default LoginFormHelpText; diff --git a/frontend/app/components/login/LoginFormTitle.tsx b/frontend/app/components/login/LoginFormTitle.tsx index 5ede68eb..2e3d7b65 100644 --- a/frontend/app/components/login/LoginFormTitle.tsx +++ b/frontend/app/components/login/LoginFormTitle.tsx @@ -1,15 +1,11 @@ -import { Text } from '@mantine/core' +import { Text } from '@mantine/core'; const LoginFormTitle = () => { - return ( - - ログイン - - ) -} + return ( + + ログイン + + ); +}; -export default LoginFormTitle \ No newline at end of file +export default LoginFormTitle; diff --git a/frontend/app/components/login/LoginPasswordForm.tsx b/frontend/app/components/login/LoginPasswordForm.tsx index a3982cf2..93851423 100644 --- a/frontend/app/components/login/LoginPasswordForm.tsx +++ b/frontend/app/components/login/LoginPasswordForm.tsx @@ -1,22 +1,22 @@ -import { PasswordInput } from "@mantine/core"; -import type { UseFormReturnType } from "@mantine/form"; -import type { LoginBody } from "client/client.schemas"; +import { PasswordInput } from '@mantine/core'; +import type { UseFormReturnType } from '@mantine/form'; +import type { LoginBody } from 'client/client.schemas'; interface LoginPasswordFormProps { - form: UseFormReturnType LoginBody>; + form: UseFormReturnType LoginBody>; } const LoginPasswordForm = ({ form }: LoginPasswordFormProps) => { - return ( - - ); + return ( + + ); }; export default LoginPasswordForm; diff --git a/frontend/app/components/login/LoginSubmitButton.tsx b/frontend/app/components/login/LoginSubmitButton.tsx index a3feaea1..82bb3a74 100644 --- a/frontend/app/components/login/LoginSubmitButton.tsx +++ b/frontend/app/components/login/LoginSubmitButton.tsx @@ -1,18 +1,15 @@ -import { Button } from '@mantine/core' +import { Button } from '@mantine/core'; interface LoginSubmitButtonProps { - isPending: boolean + isPending: boolean; } -const LoginSubmitButton = ({isPending}: LoginSubmitButtonProps) => { - return ( - - ) -} +const LoginSubmitButton = ({ isPending }: LoginSubmitButtonProps) => { + return ( + + ); +}; -export default LoginSubmitButton \ No newline at end of file +export default LoginSubmitButton; diff --git a/frontend/app/components/login/LoginTitle.tsx b/frontend/app/components/login/LoginTitle.tsx index 205c6976..989858de 100644 --- a/frontend/app/components/login/LoginTitle.tsx +++ b/frontend/app/components/login/LoginTitle.tsx @@ -1,15 +1,11 @@ -import { Text } from '@mantine/core' +import { Text } from '@mantine/core'; const LoginTitle = () => { - return ( - - ログイン - - ) -} + return ( + + ログイン + + ); +}; -export default LoginTitle \ No newline at end of file +export default LoginTitle; diff --git a/frontend/app/entry.client.tsx b/frontend/app/entry.client.tsx index 94d5dc0d..ee067085 100644 --- a/frontend/app/entry.client.tsx +++ b/frontend/app/entry.client.tsx @@ -4,15 +4,15 @@ * For more information, see https://remix.run/file-conventions/entry.client */ -import { RemixBrowser } from "@remix-run/react"; -import { startTransition, StrictMode } from "react"; -import { hydrateRoot } from "react-dom/client"; +import { RemixBrowser } from '@remix-run/react'; +import { startTransition, StrictMode } from 'react'; +import { hydrateRoot } from 'react-dom/client'; startTransition(() => { - hydrateRoot( - document, - - - - ); + hydrateRoot( + document, + + + , + ); }); diff --git a/frontend/app/entry.server.tsx b/frontend/app/entry.server.tsx index 0d5c40a7..58dcf4c3 100644 --- a/frontend/app/entry.server.tsx +++ b/frontend/app/entry.server.tsx @@ -4,40 +4,40 @@ * For more information, see https://remix.run/file-conventions/entry.server */ -import type { AppLoadContext, EntryContext } from "@remix-run/cloudflare"; -import { RemixServer } from "@remix-run/react"; -import { isbot } from "isbot"; -import { renderToReadableStream } from "react-dom/server"; +import type { AppLoadContext, EntryContext } from '@remix-run/cloudflare'; +import { RemixServer } from '@remix-run/react'; +import { isbot } from 'isbot'; +import { renderToReadableStream } from 'react-dom/server'; export default async function handleRequest( - request: Request, - responseStatusCode: number, - responseHeaders: Headers, - remixContext: EntryContext, - // This is ignored so we can keep it in the template for visibility. Feel - // free to delete this parameter in your app if you're not using it! - // eslint-disable-next-line @typescript-eslint/no-unused-vars - loadContext: AppLoadContext + request: Request, + responseStatusCode: number, + responseHeaders: Headers, + remixContext: EntryContext, + // This is ignored so we can keep it in the template for visibility. Feel + // free to delete this parameter in your app if you're not using it! + // eslint-disable-next-line @typescript-eslint/no-unused-vars + loadContext: AppLoadContext, ) { - const body = await renderToReadableStream( - , - { - signal: request.signal, - onError(error: unknown) { - // Log streaming rendering errors from inside the shell - console.error(error); - responseStatusCode = 500; - }, - } - ); + const body = await renderToReadableStream( + , + { + signal: request.signal, + onError(error: unknown) { + // Log streaming rendering errors from inside the shell + console.error(error); + responseStatusCode = 500; + }, + }, + ); - if (isbot(request.headers.get("user-agent") || "")) { - await body.allReady; - } + if (isbot(request.headers.get('user-agent') || '')) { + await body.allReady; + } - responseHeaders.set("Content-Type", "text/html"); - return new Response(body, { - headers: responseHeaders, - status: responseStatusCode, - }); + responseHeaders.set('Content-Type', 'text/html'); + return new Response(body, { + headers: responseHeaders, + status: responseStatusCode, + }); } diff --git a/frontend/app/root.tsx b/frontend/app/root.tsx index 46f11e0b..e3e966e1 100644 --- a/frontend/app/root.tsx +++ b/frontend/app/root.tsx @@ -1,56 +1,56 @@ import '@mantine/core/styles.css'; import '@mantine/notifications/styles.css'; -import type { LinksFunction } from "@remix-run/cloudflare"; +import type { LinksFunction } from '@remix-run/cloudflare'; import { - Links, - Meta, - Outlet, - Scripts, - ScrollRestoration, -} from "@remix-run/react"; + Links, + Meta, + Outlet, + Scripts, + ScrollRestoration, +} from '@remix-run/react'; import { ColorSchemeScript, MantineProvider } from '@mantine/core'; import { Notifications } from '@mantine/notifications'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; export const links: LinksFunction = () => [ - { rel: "preconnect", href: "https://fonts.googleapis.com" }, - { - rel: "preconnect", - href: "https://fonts.gstatic.com", - crossOrigin: "anonymous", - }, - { - rel: "stylesheet", - href: "https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap", - }, + { rel: 'preconnect', href: 'https://fonts.googleapis.com' }, + { + rel: 'preconnect', + href: 'https://fonts.gstatic.com', + crossOrigin: 'anonymous', + }, + { + rel: 'stylesheet', + href: 'https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap', + }, ]; const queryClient = new QueryClient(); export function Layout({ children }: { children: React.ReactNode }) { - return ( - - - - - - - - - - - - - {children} - - - - - - - ); + return ( + + + + + + + + + + + + + {children} + + + + + + + ); } export default function App() { - return ; + return ; } diff --git a/frontend/app/routes/_index.tsx b/frontend/app/routes/_index.tsx index 554dd06d..8631958b 100644 --- a/frontend/app/routes/_index.tsx +++ b/frontend/app/routes/_index.tsx @@ -1,13 +1,13 @@ -import { redirect, type MetaFunction } from "@remix-run/cloudflare"; -import { Text } from "@mantine/core"; +import { redirect, type MetaFunction } from '@remix-run/cloudflare'; +import { Text } from '@mantine/core'; export const meta: MetaFunction = () => { - return [ - { title: "New Remix App" }, - { name: "description", content: "Welcome to Remix!" }, - ]; + return [ + { title: 'New Remix App' }, + { name: 'description', content: 'Welcome to Remix!' }, + ]; }; export async function loader() { - return redirect('home') + return redirect('home'); } diff --git a/frontend/app/routes/auth.login.tsx b/frontend/app/routes/auth.login.tsx index 0135fa8d..98330e09 100644 --- a/frontend/app/routes/auth.login.tsx +++ b/frontend/app/routes/auth.login.tsx @@ -1,84 +1,84 @@ -import { useForm } from "@mantine/form"; -import { useNavigate } from "@remix-run/react"; -import { useLogin } from "client/client"; -import type { LoginBody } from "client/client.schemas"; -import { useAtom } from "jotai"; -import LoginFormComponent from "~/components/login/LoginFormComponent"; -import { userAtom } from "~/stores/userAtom"; -import { errorNotifications, successNotifications } from "~/utils/notification"; +import { useForm } from '@mantine/form'; +import { useNavigate } from '@remix-run/react'; +import { useLogin } from 'client/client'; +import type { LoginBody } from 'client/client.schemas'; +import { useAtom } from 'jotai'; +import LoginFormComponent from '~/components/login/LoginFormComponent'; +import { userAtom } from '~/stores/userAtom'; +import { errorNotifications, successNotifications } from '~/utils/notification'; const LoginPage = () => { - const loginTask = useLogin(); - const navigate = useNavigate(); - const [, setUser] = useAtom(userAtom); - const form = useForm({ - mode: "uncontrolled", - initialValues: { - email: "", - password: "", - }, - validate: { - email: (value) => - /^[\w+\-.]+@[a-z\d-]+(\.[a-z\d-]+)*\.[a-z]+$/i.test(value) - ? null - : "有効でないメールアドレスです", - password: (value) => { - if (value.length < 8) return "パスワードは8文字以上で入力してください"; - else if (/^(?=.*[A-Za-z])(?=.*\d)[A-Za-z\d]+$/.test(value)) return null; - else return "パスワードにはアルファベットと数字を含めてください"; - }, - }, - }); + const loginTask = useLogin(); + const navigate = useNavigate(); + const [, setUser] = useAtom(userAtom); + const form = useForm({ + mode: 'uncontrolled', + initialValues: { + email: '', + password: '', + }, + validate: { + email: (value) => + /^[\w+\-.]+@[a-z\d-]+(\.[a-z\d-]+)*\.[a-z]+$/i.test(value) + ? null + : '有効でないメールアドレスです', + password: (value) => { + if (value.length < 8) return 'パスワードは8文字以上で入力してください'; + else if (/^(?=.*[A-Za-z])(?=.*\d)[A-Za-z\d]+$/.test(value)) return null; + else return 'パスワードにはアルファベットと数字を含めてください'; + }, + }, + }); - const handleSubmit = (props: LoginBody) => { - loginTask.mutate( - { - data: props, - }, - { - onSuccess: (response) => { - switch (response.status) { - case 200: - successNotifications("ログインに成功しました"); - setUser(response.data); - navigate("/home/mypage"); - break; - case 400: - errorNotifications( - "メールアドレスまたはパスワードが間違っています" - ); - break; - case 401: - errorNotifications( - "メールアドレスまたはパスワードが間違っています" - ); - break; - case 404: - errorNotifications("ユーザーが見つかりません"); - break; - case 500: - errorNotifications("サーバーエラーが発生しました"); - break; - default: - errorNotifications("エラーが発生しました"); - } - }, - onError: () => { - errorNotifications( - "APIに問題が発生しています。サーバが起動されているか確認してください。" - ); - }, - } - ); - }; + const handleSubmit = (props: LoginBody) => { + loginTask.mutate( + { + data: props, + }, + { + onSuccess: (response) => { + switch (response.status) { + case 200: + successNotifications('ログインに成功しました'); + setUser(response.data); + navigate('/home/mypage'); + break; + case 400: + errorNotifications( + 'メールアドレスまたはパスワードが間違っています', + ); + break; + case 401: + errorNotifications( + 'メールアドレスまたはパスワードが間違っています', + ); + break; + case 404: + errorNotifications('ユーザーが見つかりません'); + break; + case 500: + errorNotifications('サーバーエラーが発生しました'); + break; + default: + errorNotifications('エラーが発生しました'); + } + }, + onError: () => { + errorNotifications( + 'APIに問題が発生しています。サーバが起動されているか確認してください。', + ); + }, + }, + ); + }; - return ( - - ); + return ( + + ); }; export default LoginPage; diff --git a/frontend/app/routes/home._index.tsx b/frontend/app/routes/home._index.tsx index 3cb986a0..f3312bbc 100644 --- a/frontend/app/routes/home._index.tsx +++ b/frontend/app/routes/home._index.tsx @@ -1,186 +1,186 @@ -import { useForm } from "@mantine/form"; -import { useDisclosure } from "@mantine/hooks"; -import type { LoaderFunctionArgs } from "@remix-run/cloudflare"; -import { json } from "@remix-run/cloudflare"; -import { useLoaderData, useNavigate } from "@remix-run/react"; -import { getBooks } from "client/client"; -import { GetBooksParams } from "client/client.schemas"; -import { useAtom } from "jotai"; -import { useEffect } from "react"; -import BookListComponent from "~/components/books/BookListComponent"; -import { selectedBooksAtom } from "~/stores/cartAtom"; +import { useForm } from '@mantine/form'; +import { useDisclosure } from '@mantine/hooks'; +import type { LoaderFunctionArgs } from '@remix-run/cloudflare'; +import { json } from '@remix-run/cloudflare'; +import { useLoaderData, useNavigate } from '@remix-run/react'; +import { getBooks } from 'client/client'; +import { GetBooksParams } from 'client/client.schemas'; +import { useAtom } from 'jotai'; +import { useEffect } from 'react'; +import BookListComponent from '~/components/books/BookListComponent'; +import { selectedBooksAtom } from '~/stores/cartAtom'; export const loader = async ({ request }: LoaderFunctionArgs) => { - const url = new URL(request.url); - const title = url.searchParams.get("title") ?? undefined; - const publisher = url.searchParams.get("publisher") ?? undefined; - const isbn = url.searchParams.get("isbn") ?? undefined; - const auther = url.searchParams.get("author") ?? undefined; - const page = url.searchParams.get("page") ?? undefined; - const limit = url.searchParams.get("limit") ?? undefined; - const response = await getBooks({ - title: title, - author: auther, - publisher: publisher, - isbn: isbn, - page: page, - limit: limit, - }); - return json({ - booksResponse: response, - title: title, - author: auther, - publisher: publisher, - isbn: isbn, - page: page, - limit: limit, - }); + const url = new URL(request.url); + const title = url.searchParams.get('title') ?? undefined; + const publisher = url.searchParams.get('publisher') ?? undefined; + const isbn = url.searchParams.get('isbn') ?? undefined; + const auther = url.searchParams.get('author') ?? undefined; + const page = url.searchParams.get('page') ?? undefined; + const limit = url.searchParams.get('limit') ?? undefined; + const response = await getBooks({ + title: title, + author: auther, + publisher: publisher, + isbn: isbn, + page: page, + limit: limit, + }); + return json({ + booksResponse: response, + title: title, + author: auther, + publisher: publisher, + isbn: isbn, + page: page, + limit: limit, + }); }; const BooKListPage = () => { - const { booksResponse, title, author, publisher, isbn, page, limit } = - useLoaderData(); - const [opened, { open, close }] = useDisclosure(); - const navigate = useNavigate(); - const [, setSelectedBook] = useAtom(selectedBooksAtom); - const form = useForm({ - mode: "uncontrolled", - initialValues: { - title: title ?? "", - author: author ?? "", - publisher: publisher ?? "", - isbn: isbn ?? "", - }, - }); + const { booksResponse, title, author, publisher, isbn, page, limit } = + useLoaderData(); + const [opened, { open, close }] = useDisclosure(); + const navigate = useNavigate(); + const [, setSelectedBook] = useAtom(selectedBooksAtom); + const form = useForm({ + mode: 'uncontrolled', + initialValues: { + title: title ?? '', + author: author ?? '', + publisher: publisher ?? '', + isbn: isbn ?? '', + }, + }); - // 選択中の書籍をリセットする - useEffect(() => { - setSelectedBook([]); - }, []); + // 選択中の書籍をリセットする + useEffect(() => { + setSelectedBook([]); + }, []); - const handleSubmit = (props: GetBooksParams) => { - let url = "/home"; - let initial = true; - if (props.title && props.title !== "") { - url = - initial === true - ? `${url}?title=${props.title}` - : `${url}&title=${props.title}`; - initial = false; - } - if (props.author && props.author !== "") { - url = - initial === true - ? `${url}?author=${props.author}` - : `${url}&author=${props.author}`; - initial = false; - } - if (props.publisher && props.publisher !== "") { - url = - initial === true - ? `${url}?publisher=${props.publisher}` - : `${url}&publisher=${props.publisher}`; - initial = false; - } - if (props.isbn && props.isbn !== "") { - url = - initial === true - ? `${url}?isbn=${props.isbn}` - : `${url}&isbn=${props.isbn}`; - initial = false; - } - if (limit) { - url = - initial === true ? `${url}?limit=${limit}` : `${url}&limit=${limit}`; - initial = false; - } - navigate(url); - }; + const handleSubmit = (props: GetBooksParams) => { + let url = '/home'; + let initial = true; + if (props.title && props.title !== '') { + url = + initial === true + ? `${url}?title=${props.title}` + : `${url}&title=${props.title}`; + initial = false; + } + if (props.author && props.author !== '') { + url = + initial === true + ? `${url}?author=${props.author}` + : `${url}&author=${props.author}`; + initial = false; + } + if (props.publisher && props.publisher !== '') { + url = + initial === true + ? `${url}?publisher=${props.publisher}` + : `${url}&publisher=${props.publisher}`; + initial = false; + } + if (props.isbn && props.isbn !== '') { + url = + initial === true + ? `${url}?isbn=${props.isbn}` + : `${url}&isbn=${props.isbn}`; + initial = false; + } + if (limit) { + url = + initial === true ? `${url}?limit=${limit}` : `${url}&limit=${limit}`; + initial = false; + } + navigate(url); + }; - const handlePaginationChange = (newPage: number) => { - let url = "/home"; - let initial = true; - if (title) { - url = - initial === true ? `${url}?title=${title}` : `${url}&title=${title}`; - initial = false; - } - if (author) { - url = - initial === true - ? `${url}?author=${author}` - : `${url}&author=${author}`; - initial = false; - } - if (publisher) { - url = - initial === true - ? `${url}?publisher=${publisher}` - : `${url}&publisher=${publisher}`; - initial = false; - } - if (isbn) { - url = initial === true ? `${url}?isbn=${isbn}` : `${url}&isbn=${isbn}`; - initial = false; - } - if (limit) { - url = - initial === true ? `${url}?limit=${limit}` : `${url}&limit=${limit}`; - initial = false; - } - url = - initial === true ? `${url}?page=${newPage}` : `${url}&page=${newPage}`; - navigate(url); - }; + const handlePaginationChange = (newPage: number) => { + let url = '/home'; + let initial = true; + if (title) { + url = + initial === true ? `${url}?title=${title}` : `${url}&title=${title}`; + initial = false; + } + if (author) { + url = + initial === true + ? `${url}?author=${author}` + : `${url}&author=${author}`; + initial = false; + } + if (publisher) { + url = + initial === true + ? `${url}?publisher=${publisher}` + : `${url}&publisher=${publisher}`; + initial = false; + } + if (isbn) { + url = initial === true ? `${url}?isbn=${isbn}` : `${url}&isbn=${isbn}`; + initial = false; + } + if (limit) { + url = + initial === true ? `${url}?limit=${limit}` : `${url}&limit=${limit}`; + initial = false; + } + url = + initial === true ? `${url}?page=${newPage}` : `${url}&page=${newPage}`; + navigate(url); + }; - const handleLimitChange = (newLimit: number) => { - let url = "/home"; - let initial = true; - if (title) { - url = - initial === true ? `${url}?title=${title}` : `${url}&title=${title}`; - initial = false; - } - if (author) { - url = - initial === true - ? `${url}?author=${author}` - : `${url}&author=${author}`; - initial = false; - } - if (publisher) { - url = - initial === true - ? `${url}?publisher=${publisher}` - : `${url}&publisher=${publisher}`; - initial = false; - } - if (isbn) { - url = initial === true ? `${url}?isbn=${isbn}` : `${url}&isbn=${isbn}`; - initial = false; - } - url = - initial === true - ? `${url}?limit=${newLimit}` - : `${url}&limit=${newLimit}`; - navigate(url); - }; + const handleLimitChange = (newLimit: number) => { + let url = '/home'; + let initial = true; + if (title) { + url = + initial === true ? `${url}?title=${title}` : `${url}&title=${title}`; + initial = false; + } + if (author) { + url = + initial === true + ? `${url}?author=${author}` + : `${url}&author=${author}`; + initial = false; + } + if (publisher) { + url = + initial === true + ? `${url}?publisher=${publisher}` + : `${url}&publisher=${publisher}`; + initial = false; + } + if (isbn) { + url = initial === true ? `${url}?isbn=${isbn}` : `${url}&isbn=${isbn}`; + initial = false; + } + url = + initial === true + ? `${url}?limit=${newLimit}` + : `${url}&limit=${newLimit}`; + navigate(url); + }; - return ( - - ); + return ( + + ); }; export default BooKListPage; diff --git a/frontend/app/routes/home.books.$bookId.tsx b/frontend/app/routes/home.books.$bookId.tsx index b8475b28..3446069d 100644 --- a/frontend/app/routes/home.books.$bookId.tsx +++ b/frontend/app/routes/home.books.$bookId.tsx @@ -1,55 +1,55 @@ import type { - ActionFunctionArgs, - LoaderFunctionArgs, -} from "@remix-run/cloudflare"; -import { json, redirect } from "@remix-run/cloudflare"; -import { useLoaderData } from "@remix-run/react"; -import { deleteBook, getBook } from "client/client"; -import BookDetailComponent from "~/components/book-detail/BookDetailComponent"; -import { errorNotifications, successNotifications } from "~/utils/notification"; + ActionFunctionArgs, + LoaderFunctionArgs, +} from '@remix-run/cloudflare'; +import { json, redirect } from '@remix-run/cloudflare'; +import { useLoaderData } from '@remix-run/react'; +import { deleteBook, getBook } from 'client/client'; +import BookDetailComponent from '~/components/book-detail/BookDetailComponent'; +import { errorNotifications, successNotifications } from '~/utils/notification'; interface Response { - method: string; - status: number; + method: string; + status: number; } export const loader = async ({ params }: LoaderFunctionArgs) => { - const bookId = params.bookId ?? ""; - const response = await getBook(bookId); - return json({ bookResponse: response }); + const bookId = params.bookId ?? ''; + const response = await getBook(bookId); + return json({ bookResponse: response }); }; export const action = async ({ request }: ActionFunctionArgs) => { - // delete: 本の削除 - const cookieHeader = request.headers.get("Cookie"); - const formData = await request.formData(); - if (request.method === "DELETE") { - const bookId = String(formData.get("bookId")); - const response = await deleteBook(bookId, { - headers: { Cookie: cookieHeader ?? "" }, - }); - switch (response.status) { - case 204: - successNotifications("削除しました"); - return redirect("/home"); - case 401: - errorNotifications("ログインしてください"); - return redirect("/auth/login"); - case 404: - errorNotifications("書籍が見つかりませんでした"); - return redirect("/home"); - case 500: - errorNotifications("サーバーエラーが発生しました"); - return json({ method: "DELETE", status: 500 }); - } - } + // delete: 本の削除 + const cookieHeader = request.headers.get('Cookie'); + const formData = await request.formData(); + if (request.method === 'DELETE') { + const bookId = String(formData.get('bookId')); + const response = await deleteBook(bookId, { + headers: { Cookie: cookieHeader ?? '' }, + }); + switch (response.status) { + case 204: + successNotifications('削除しました'); + return redirect('/home'); + case 401: + errorNotifications('ログインしてください'); + return redirect('/auth/login'); + case 404: + errorNotifications('書籍が見つかりませんでした'); + return redirect('/home'); + case 500: + errorNotifications('サーバーエラーが発生しました'); + return json({ method: 'DELETE', status: 500 }); + } + } - return null; + return null; }; const BookDetailPage = () => { - const { bookResponse } = useLoaderData(); - return ; + const { bookResponse } = useLoaderData(); + return ; }; export default BookDetailPage; diff --git a/frontend/app/routes/home.mypage.tsx b/frontend/app/routes/home.mypage.tsx index 9c562560..60cbb0ea 100644 --- a/frontend/app/routes/home.mypage.tsx +++ b/frontend/app/routes/home.mypage.tsx @@ -1,7 +1,5 @@ const MyPage = () => { - return ( -
MyPage
- ) -} + return
MyPage
; +}; -export default MyPage \ No newline at end of file +export default MyPage; diff --git a/frontend/app/routes/home.tsx b/frontend/app/routes/home.tsx index 1eda470b..67068452 100644 --- a/frontend/app/routes/home.tsx +++ b/frontend/app/routes/home.tsx @@ -1,21 +1,18 @@ -import { Outlet } from '@remix-run/react' -import { AppShell, Container } from '@mantine/core' -import HeaderComponent from '~/components/header/HeaderComponent' +import { Outlet } from '@remix-run/react'; +import { AppShell, Container } from '@mantine/core'; +import HeaderComponent from '~/components/header/HeaderComponent'; const Home = () => { - return ( - - - - - - - - - ) -} + return ( + + + + + + + + + ); +}; -export default Home \ No newline at end of file +export default Home; diff --git a/frontend/app/stores/cartAtom.ts b/frontend/app/stores/cartAtom.ts index 0444ea30..8f5ea400 100644 --- a/frontend/app/stores/cartAtom.ts +++ b/frontend/app/stores/cartAtom.ts @@ -1,14 +1,14 @@ -import { atom } from "jotai"; -import { createJSONStorage, atomWithStorage } from "jotai/utils"; +import { atom } from 'jotai'; +import { createJSONStorage, atomWithStorage } from 'jotai/utils'; const storage = createJSONStorage(() => sessionStorage); export interface CartProps { - id: number - stock: number + id: number; + stock: number; } // カートの中身を管理するAtom 生存時間: セッションストレージ(タブが閉じられるまで) export const cartAtom = atomWithStorage('cart', [], storage); // 選択された本を管理するAtom 生存時間: DOM(ページをリロードするまで) -export const selectedBooksAtom = atom([]); \ No newline at end of file +export const selectedBooksAtom = atom([]); diff --git a/frontend/app/stores/userAtom.ts b/frontend/app/stores/userAtom.ts index 41c3bc48..3c031f4e 100644 --- a/frontend/app/stores/userAtom.ts +++ b/frontend/app/stores/userAtom.ts @@ -1,12 +1,12 @@ -import type { User } from "client/client.schemas"; -import { atomWithStorage, createJSONStorage } from "jotai/utils"; +import type { User } from 'client/client.schemas'; +import { atomWithStorage, createJSONStorage } from 'jotai/utils'; const storage = createJSONStorage(() => sessionStorage); // ユーザ情報を管理するAtom // 生存時間: セッションストレージ(タブが閉じられるまで) export const userAtom = atomWithStorage( - "user", - undefined, - storage + 'user', + undefined, + storage, ); diff --git a/frontend/app/utils/notification.ts b/frontend/app/utils/notification.ts index f9072e23..6f03c8b4 100644 --- a/frontend/app/utils/notification.ts +++ b/frontend/app/utils/notification.ts @@ -1,19 +1,17 @@ -import { notifications } from "@mantine/notifications" - - +import { notifications } from '@mantine/notifications'; export const successNotifications = (message: string) => { - notifications.show({ - title: 'Success', - message, - color: 'teal', - }) -} + notifications.show({ + title: 'Success', + message, + color: 'teal', + }); +}; export const errorNotifications = (message: string) => { - notifications.show({ - title: 'Error', - message, - color: 'red' - }) -} \ No newline at end of file + notifications.show({ + title: 'Error', + message, + color: 'red', + }); +}; diff --git a/frontend/functions/[[path]].ts b/frontend/functions/[[path]].ts index 26a7de6b..9440dce6 100644 --- a/frontend/functions/[[path]].ts +++ b/frontend/functions/[[path]].ts @@ -1,8 +1,8 @@ -import { createPagesFunctionHandler } from "@remix-run/cloudflare-pages"; +import { createPagesFunctionHandler } from '@remix-run/cloudflare-pages'; // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore - the server build file is generated by `remix vite:build` // eslint-disable-next-line import/no-unresolved -import * as build from "../build/server"; +import * as build from '../build/server'; export const onRequest = createPagesFunctionHandler({ build }); diff --git a/frontend/load-context.ts b/frontend/load-context.ts index 94ca2e1d..29245ac5 100644 --- a/frontend/load-context.ts +++ b/frontend/load-context.ts @@ -1,9 +1,9 @@ -import { type PlatformProxy } from "wrangler"; +import { type PlatformProxy } from 'wrangler'; -type Cloudflare = Omit, "dispose">; +type Cloudflare = Omit, 'dispose'>; -declare module "@remix-run/cloudflare" { - interface AppLoadContext { - cloudflare: Cloudflare; - } -} \ No newline at end of file +declare module '@remix-run/cloudflare' { + interface AppLoadContext { + cloudflare: Cloudflare; + } +} diff --git a/frontend/test/helpers/wrapper.tsx b/frontend/test/helpers/wrapper.tsx index 84d1dbe8..7d234ecd 100644 --- a/frontend/test/helpers/wrapper.tsx +++ b/frontend/test/helpers/wrapper.tsx @@ -1,29 +1,29 @@ -import { MantineProvider } from "@mantine/core"; -import { Notifications } from "@mantine/notifications"; -import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; -import { render } from "@testing-library/react"; -import userEvent from "@testing-library/user-event"; -import { ReactElement } from "react"; +import { MantineProvider } from '@mantine/core'; +import { Notifications } from '@mantine/notifications'; +import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; +import { render } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import { ReactElement } from 'react'; export const renderWithWrapper = (children: ReactElement) => { - const queryClient = new QueryClient({ - defaultOptions: { - queries: { - retry: false, - // データが古いと判断されるまでの時間[ms] - staleTime: Infinity, - }, - }, - }); - return { - user: userEvent.setup(), - ...render( - - - - {children} - - - ), - }; + const queryClient = new QueryClient({ + defaultOptions: { + queries: { + retry: false, + // データが古いと判断されるまでの時間[ms] + staleTime: Infinity, + }, + }, + }); + return { + user: userEvent.setup(), + ...render( + + + + {children} + + , + ), + }; }; diff --git a/frontend/test/routes/auth.login.test.tsx b/frontend/test/routes/auth.login.test.tsx index b848efc7..d75f6c98 100644 --- a/frontend/test/routes/auth.login.test.tsx +++ b/frontend/test/routes/auth.login.test.tsx @@ -1,77 +1,77 @@ -import { screen } from "@testing-library/react"; -import { renderWithWrapper } from "test/helpers/wrapper"; -import LoginPage from "~/routes/auth.login"; - -describe("Login page", () => { - it("should login successfully", async () => { - const { user } = renderWithWrapper(); - - // メールアドレスを入力 - const emailForm = screen.getByTestId("email-input"); - await user.type(emailForm, "user@example.com"); - expect(emailForm).toHaveValue("user@example.com"); - - // パスワードを入力 - const passwordForm = screen.getByTestId("password-input"); - await user.type(passwordForm, "passw0rd"); - expect(passwordForm).toHaveValue("passw0rd"); - - // ログインボタンをクリック - const submitButton = screen.getByRole("button", { name: "ログイン" }); - await user.click(submitButton); - - // ログイン成功の通知が表示される - const banner = await screen.findByText("ログインに成功しました"); - expect(banner).toBeInTheDocument(); - }); - - it("should fail to pass when email is invalid", async () => { - const { user } = renderWithWrapper(); - - // メールアドレスを入力 - const emailForm = screen.getByTestId("email-input"); - await user.type(emailForm, "user@invalid"); - - // ログインボタンをクリック - const submitButton = screen.getByRole("button", { name: "ログイン" }); - await user.click(submitButton); - - // エラーメッセージが表示される - const message = await screen.findByText("有効でないメールアドレスです"); - expect(message).toBeInTheDocument(); - }); - - test("should fail to pass when password length is less than 8", async () => { - const { user } = renderWithWrapper(); - - // パスワードを入力 - const passwordForm = screen.getByTestId("password-input"); - await user.type(passwordForm, "pass"); - - // ログインボタンをクリック - const submitButton = screen.getByRole("button", { name: "ログイン" }); - await user.click(submitButton); - - // エラーメッセージが表示される - // prettier-ignore - const message = await screen.findByText("パスワードは8文字以上で入力してください"); - expect(message).toBeInTheDocument(); - }); - - test("should fail to pass when password is not alphanumeric", async () => { - const { user } = renderWithWrapper(); - - // パスワードを入力 - const passwordForm = screen.getByTestId("password-input"); - await user.type(passwordForm, "password"); - - // ログインボタンをクリック - const submitButton = screen.getByRole("button", { name: "ログイン" }); - await user.click(submitButton); - - // エラーメッセージが表示される - // prettier-ignore - const message = await screen.findByText("パスワードにはアルファベットと数字を含めてください"); - expect(message).toBeInTheDocument(); - }); +import { screen } from '@testing-library/react'; +import { renderWithWrapper } from 'test/helpers/wrapper'; +import LoginPage from '~/routes/auth.login'; + +describe('Login page', () => { + it('should login successfully', async () => { + const { user } = renderWithWrapper(); + + // メールアドレスを入力 + const emailForm = screen.getByTestId('email-input'); + await user.type(emailForm, 'user@example.com'); + expect(emailForm).toHaveValue('user@example.com'); + + // パスワードを入力 + const passwordForm = screen.getByTestId('password-input'); + await user.type(passwordForm, 'passw0rd'); + expect(passwordForm).toHaveValue('passw0rd'); + + // ログインボタンをクリック + const submitButton = screen.getByRole('button', { name: 'ログイン' }); + await user.click(submitButton); + + // ログイン成功の通知が表示される + const banner = await screen.findByText('ログインに成功しました'); + expect(banner).toBeInTheDocument(); + }); + + it('should fail to pass when email is invalid', async () => { + const { user } = renderWithWrapper(); + + // メールアドレスを入力 + const emailForm = screen.getByTestId('email-input'); + await user.type(emailForm, 'user@invalid'); + + // ログインボタンをクリック + const submitButton = screen.getByRole('button', { name: 'ログイン' }); + await user.click(submitButton); + + // エラーメッセージが表示される + const message = await screen.findByText('有効でないメールアドレスです'); + expect(message).toBeInTheDocument(); + }); + + test('should fail to pass when password length is less than 8', async () => { + const { user } = renderWithWrapper(); + + // パスワードを入力 + const passwordForm = screen.getByTestId('password-input'); + await user.type(passwordForm, 'pass'); + + // ログインボタンをクリック + const submitButton = screen.getByRole('button', { name: 'ログイン' }); + await user.click(submitButton); + + // エラーメッセージが表示される + // prettier-ignore + const message = await screen.findByText("パスワードは8文字以上で入力してください"); + expect(message).toBeInTheDocument(); + }); + + test('should fail to pass when password is not alphanumeric', async () => { + const { user } = renderWithWrapper(); + + // パスワードを入力 + const passwordForm = screen.getByTestId('password-input'); + await user.type(passwordForm, 'password'); + + // ログインボタンをクリック + const submitButton = screen.getByRole('button', { name: 'ログイン' }); + await user.click(submitButton); + + // エラーメッセージが表示される + // prettier-ignore + const message = await screen.findByText("パスワードにはアルファベットと数字を含めてください"); + expect(message).toBeInTheDocument(); + }); }); diff --git a/frontend/test/setup.ts b/frontend/test/setup.ts index 4129d02e..313cebcf 100644 --- a/frontend/test/setup.ts +++ b/frontend/test/setup.ts @@ -1,31 +1,31 @@ -import "@testing-library/jest-dom/vitest"; -import { cleanup } from "@testing-library/react"; -import { setupServer } from "msw/node"; -import { handlers } from "./mocks/handlers"; +import '@testing-library/jest-dom/vitest'; +import { cleanup } from '@testing-library/react'; +import { setupServer } from 'msw/node'; +import { handlers } from './mocks/handlers'; -vi.mock("@remix-run/react", () => { - const useNavigate = vi.fn(); - const form = vi - .fn() - .mockImplementation(({ children }: { children: React.ReactElement }) => { - return children; - }); - return { - useNavigate: useNavigate, - Form: form, - }; +vi.mock('@remix-run/react', () => { + const useNavigate = vi.fn(); + const form = vi + .fn() + .mockImplementation(({ children }: { children: React.ReactElement }) => { + return children; + }); + return { + useNavigate: useNavigate, + Form: form, + }; }); const server = setupServer(...handlers); beforeAll(() => { - server.listen(); + server.listen(); }); afterEach(() => { - cleanup(); + cleanup(); }); afterAll(() => { - server.close(); + server.close(); }); diff --git a/frontend/worker-configuration.d.ts b/frontend/worker-configuration.d.ts index 5b2319b3..a3f43d2a 100644 --- a/frontend/worker-configuration.d.ts +++ b/frontend/worker-configuration.d.ts @@ -1,4 +1,3 @@ // Generated by Wrangler // After adding bindings to `wrangler.toml`, regenerate this interface via `npm run cf-typegen` -interface Env { -} +interface Env {} From 881c4163beb310d9efc42766a585677a9bdea14c Mon Sep 17 00:00:00 2001 From: shunsei Date: Sun, 27 Oct 2024 15:32:10 +0900 Subject: [PATCH 3/6] Edit comment (#97) --- frontend/app/components/books/BookCardHeader.tsx | 13 +++++++------ frontend/app/components/header/HeaderComponent.tsx | 2 +- frontend/app/routes/_index.tsx | 1 - frontend/app/stores/cartAtom.ts | 8 +++++--- 4 files changed, 13 insertions(+), 11 deletions(-) diff --git a/frontend/app/components/books/BookCardHeader.tsx b/frontend/app/components/books/BookCardHeader.tsx index cbaa332c..85d66002 100644 --- a/frontend/app/components/books/BookCardHeader.tsx +++ b/frontend/app/components/books/BookCardHeader.tsx @@ -1,8 +1,8 @@ import { Checkbox, Group } from '@mantine/core'; -import { selectedBooksAtom } from '~/stores/cartAtom'; import { useAtom } from 'jotai'; -import { userAtom } from '~/stores/userAtom'; import type { CartProps } from '~/stores/cartAtom'; +import { selectedBooksAtom } from '~/stores/cartAtom'; +import { userAtom } from '~/stores/userAtom'; import BookCardHeaderBadge from './BookCardHeaderBadge'; interface BookCardHeaderProps { @@ -13,21 +13,22 @@ interface BookCardHeaderProps { const BookCardHeader = ({ id, stock }: BookCardHeaderProps) => { const [selectedBook, setSelectedBook] = useAtom(selectedBooksAtom); const [user] = useAtom(userAtom); - // この関数は、選択されている本のIDと表示する本のIDを比較します。 + // 選択されている本のIDと表示する本のIDを比較する関数 const selectedCheck = (element: CartProps) => element.id === id; - // チェックボックスの状態が変化した時に、すでに選択されている本の配列に含まれている場合、選択を外し、 - // 選択されていなかった場合は、選択します。 const selectedBookAdd = () => { + // チェックボックスの状態が変化した時に、 if (selectedBook.some(selectedCheck)) { + // すでに選択されていた場合は選択を外す setSelectedBook(selectedBook.filter((element) => element.id !== id)); } else { + // 選択されていなかった場合は選択する setSelectedBook([...selectedBook, { id, stock }]); } }; return ( - + {!!user && ( { const userId = getCookieUserId(); if (userId) { if (!user) { - // ユーザ情報を取得するAPIを呼び出す。 + // ユーザ情報を取得するAPIを呼び出す getUser(userId).then((response) => { if (response.status === 200) { setUser(response.data as User); diff --git a/frontend/app/routes/_index.tsx b/frontend/app/routes/_index.tsx index 8631958b..2eb33bec 100644 --- a/frontend/app/routes/_index.tsx +++ b/frontend/app/routes/_index.tsx @@ -1,5 +1,4 @@ import { redirect, type MetaFunction } from '@remix-run/cloudflare'; -import { Text } from '@mantine/core'; export const meta: MetaFunction = () => { return [ diff --git a/frontend/app/stores/cartAtom.ts b/frontend/app/stores/cartAtom.ts index 8f5ea400..a0d681cf 100644 --- a/frontend/app/stores/cartAtom.ts +++ b/frontend/app/stores/cartAtom.ts @@ -1,5 +1,5 @@ import { atom } from 'jotai'; -import { createJSONStorage, atomWithStorage } from 'jotai/utils'; +import { atomWithStorage, createJSONStorage } from 'jotai/utils'; const storage = createJSONStorage(() => sessionStorage); export interface CartProps { @@ -7,8 +7,10 @@ export interface CartProps { stock: number; } -// カートの中身を管理するAtom 生存時間: セッションストレージ(タブが閉じられるまで) +// カートの中身を管理するAtom +// 生存時間: セッションストレージ(タブが閉じられるまで) export const cartAtom = atomWithStorage('cart', [], storage); -// 選択された本を管理するAtom 生存時間: DOM(ページをリロードするまで) +// 選択された本を管理するAtom +// 生存時間: DOM(ページをリロードするまで) export const selectedBooksAtom = atom([]); From 83ac7ecb52c88c73b858c67d1c379f215b238c23 Mon Sep 17 00:00:00 2001 From: shunsei Date: Sun, 27 Oct 2024 16:16:09 +0900 Subject: [PATCH 4/6] Install prettier & eslint-config-prettier (#97) --- frontend/package.json | 2 ++ frontend/pnpm-lock.yaml | 23 +++++++++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/frontend/package.json b/frontend/package.json index fd1e4b0b..e6704772 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -50,6 +50,7 @@ "@typescript-eslint/parser": "^6.7.4", "autoprefixer": "^10.4.19", "eslint": "^8.57.1", + "eslint-config-prettier": "^9.1.0", "eslint-import-resolver-typescript": "^3.6.1", "eslint-plugin-import": "^2.28.1", "eslint-plugin-jsx-a11y": "^6.7.1", @@ -61,6 +62,7 @@ "postcss": "^8.4.47", "postcss-preset-mantine": "^1.17.0", "postcss-simple-vars": "^7.0.1", + "prettier": "^3.3.3", "typescript": "^5.1.6", "vite": "^5.1.0", "vite-tsconfig-paths": "^4.2.1", diff --git a/frontend/pnpm-lock.yaml b/frontend/pnpm-lock.yaml index 6f97bbd8..e401125c 100644 --- a/frontend/pnpm-lock.yaml +++ b/frontend/pnpm-lock.yaml @@ -90,6 +90,9 @@ importers: eslint: specifier: ^8.57.1 version: 8.57.1 + eslint-config-prettier: + specifier: ^9.1.0 + version: 9.1.0(eslint@8.57.1) eslint-import-resolver-typescript: specifier: ^3.6.1 version: 3.6.3(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.6.2))(eslint-plugin-import@2.31.0)(eslint@8.57.1) @@ -123,6 +126,9 @@ importers: postcss-simple-vars: specifier: ^7.0.1 version: 7.0.1(postcss@8.4.47) + prettier: + specifier: ^3.3.3 + version: 3.3.3 typescript: specifier: ^5.1.6 version: 5.6.2 @@ -2301,6 +2307,12 @@ packages: resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} engines: {node: '>=10'} + eslint-config-prettier@9.1.0: + resolution: {integrity: sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==} + hasBin: true + peerDependencies: + eslint: '>=7.0.0' + eslint-import-resolver-node@0.3.9: resolution: {integrity: sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==} @@ -3792,6 +3804,11 @@ packages: engines: {node: '>=10.13.0'} hasBin: true + prettier@3.3.3: + resolution: {integrity: sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==} + engines: {node: '>=14'} + hasBin: true + pretty-format@27.5.1: resolution: {integrity: sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} @@ -7340,6 +7357,10 @@ snapshots: escape-string-regexp@4.0.0: {} + eslint-config-prettier@9.1.0(eslint@8.57.1): + dependencies: + eslint: 8.57.1 + eslint-import-resolver-node@0.3.9: dependencies: debug: 3.2.7 @@ -9131,6 +9152,8 @@ snapshots: prettier@2.8.8: {} + prettier@3.3.3: {} + pretty-format@27.5.1: dependencies: ansi-regex: 5.0.1 From e25ec3c4c3d3ef700f20aced50519690b9babf8a Mon Sep 17 00:00:00 2001 From: shunsei Date: Sun, 27 Oct 2024 16:17:00 +0900 Subject: [PATCH 5/6] Edit .eslintrc.cjs (#97) (#) --- .vscode/settings.json | 13 ++-- frontend/.eslintrc.cjs | 147 +++++++++++++++++++++-------------------- 2 files changed, 83 insertions(+), 77 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index e40d8393..d5bdd38d 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,8 +1,9 @@ { - "editor.defaultFormatter": "esbenp.prettier-vscode", - "editor.formatOnSave": true, - "editor.codeActionsOnSave": { - "source.fixAll.eslint": "explicit" - }, - "prettier.configPath": ".prettierrc", + "editor.defaultFormatter": "esbenp.prettier-vscode", + "editor.formatOnSave": true, + "editor.codeActionsOnSave": { + "source.fixAll.eslint": "explicit" + }, + "eslint.workingDirectories": ["./frontend", "./backend"], + "prettier.configPath": ".prettierrc" } diff --git a/frontend/.eslintrc.cjs b/frontend/.eslintrc.cjs index 4f6f59ee..a9109739 100644 --- a/frontend/.eslintrc.cjs +++ b/frontend/.eslintrc.cjs @@ -6,79 +6,84 @@ /** @type {import('eslint').Linter.Config} */ module.exports = { - root: true, - parserOptions: { - ecmaVersion: "latest", - sourceType: "module", - ecmaFeatures: { - jsx: true, - }, - }, - env: { - browser: true, - commonjs: true, - es6: true, - }, - ignorePatterns: ["!**/.server", "!**/.client"], + root: true, + parserOptions: { + ecmaVersion: 'latest', + sourceType: 'module', + ecmaFeatures: { + jsx: true, + }, + }, + env: { + browser: true, + commonjs: true, + es6: true, + }, + ignorePatterns: ['!**/.server', '!**/.client'], - // Base config - extends: ["eslint:recommended"], + // Base config + extends: ['eslint:recommended', 'prettier'], - overrides: [ - // React - { - files: ["**/*.{js,jsx,ts,tsx}"], - plugins: ["react", "jsx-a11y"], - extends: [ - "plugin:react/recommended", - "plugin:react/jsx-runtime", - "plugin:react-hooks/recommended", - "plugin:jsx-a11y/recommended", - ], - settings: { - react: { - version: "detect", - }, - formComponents: ["Form"], - linkComponents: [ - { name: "Link", linkAttribute: "to" }, - { name: "NavLink", linkAttribute: "to" }, - ], - "import/resolver": { - typescript: {}, - }, - }, - }, + overrides: [ + // React + { + files: ['**/*.{js,jsx,ts,tsx}'], + plugins: ['react', 'jsx-a11y'], + extends: [ + 'plugin:react/recommended', + 'plugin:react/jsx-runtime', + 'plugin:react-hooks/recommended', + 'plugin:jsx-a11y/recommended', + ], - // Typescript - { - files: ["**/*.{ts,tsx}"], - plugins: ["@typescript-eslint", "import"], - parser: "@typescript-eslint/parser", - settings: { - "import/internal-regex": "^~/", - "import/resolver": { - node: { - extensions: [".ts", ".tsx"], - }, - typescript: { - alwaysTryTypes: true, - }, - }, - }, - extends: [ - "plugin:@typescript-eslint/recommended", - "plugin:import/recommended", - "plugin:import/typescript", - ], - }, + rules: { + 'react/prop-types': 'off', + }, - // Node - { - files: [".eslintrc.cjs"], - env: { - node: true, - }, - }, - ], + settings: { + react: { + version: 'detect', + }, + formComponents: ['Form'], + linkComponents: [ + { name: 'Link', linkAttribute: 'to' }, + { name: 'NavLink', linkAttribute: 'to' }, + ], + 'import/resolver': { + typescript: {}, + }, + }, + }, + + // Typescript + { + files: ['**/*.{ts,tsx}'], + plugins: ['@typescript-eslint', 'import'], + parser: '@typescript-eslint/parser', + settings: { + 'import/internal-regex': '^~/', + 'import/resolver': { + node: { + extensions: ['.ts', '.tsx'], + }, + typescript: { + alwaysTryTypes: true, + }, + }, + }, + extends: [ + 'plugin:@typescript-eslint/recommended', + 'plugin:import/recommended', + 'plugin:import/typescript', + ], + }, + + // Node + { + files: ['.eslintrc.cjs'], + env: { + node: true, + }, + }, + ], }; From 57ac465c092203577598923327340ff0fe73876f Mon Sep 17 00:00:00 2001 From: shunsei Date: Sun, 27 Oct 2024 16:31:59 +0900 Subject: [PATCH 6/6] Delete CORS traling slash (#97) --- backend/src/index.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/backend/src/index.ts b/backend/src/index.ts index a7370aa1..339fed07 100644 --- a/backend/src/index.ts +++ b/backend/src/index.ts @@ -20,7 +20,8 @@ app.use( origin.includes('localhost') || origin.includes('kitcc-library-web.pages.dev') ? origin - : 'https://kitcc-library-web.pages.dev/'); + : 'https://kitcc-library-web.pages.dev' + ); }, // リクエストに含めることができるヘッダ allowHeaders: ['Cookie', 'Content-Type'],