Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ユーザー一覧の実装 #137

Merged
merged 8 commits into from
Nov 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
import BookDetailEditButton from './BookDetailEditButton';
import { MdDeleteForever } from 'react-icons/md';
import { Button } from '@mantine/core';
import { useFetcher } from '@remix-run/react';
import BookDetailDeleteButton from './BookDetailDeleteButton';

interface BookDetailControlButtonsProps {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import React from 'react';
import { MdDeleteForever } from 'react-icons/md';
import { Button } from '@mantine/core';
import { useFetcher } from '@remix-run/react';
Expand Down
29 changes: 11 additions & 18 deletions frontend/app/components/books/BookListComponent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import ErrorComponent from '../common/error/ErrorComponent';
import ContentsHeader from '../common/pagination/ContentsHeader';
import PaginationComponent from '../common/pagination/PaginationComponent';
import BookCards from './BookCards';
import { PaginationProps } from '~/types/paginatiion';

interface BookListComponentProps {
booksResponse: getBooksResponse;
Expand All @@ -18,11 +19,7 @@ interface BookListComponentProps {
isOpen: boolean;
open: () => void;
close: () => void;
handlePaginationChange: (newPage: number) => void;
handleLimitChange: (newLimit: number) => void;
page?: number;
limit?: number;
totalBook: number;
paginationProps: PaginationProps;
}

const BookListComponent = ({
Expand All @@ -32,11 +29,7 @@ const BookListComponent = ({
isOpen,
open,
close,
handlePaginationChange,
handleLimitChange,
page,
limit,
totalBook,
paginationProps,
}: BookListComponentProps) => {
return (
<Stack bg="var(--mantine-color-body)" align="stretch" justify="flex-start">
Expand All @@ -48,21 +41,21 @@ const BookListComponent = ({
handleSubmit={handleSubmit}
/>
<ContentsHeader
page={page}
limit={limit}
total={totalBook}
handleLimitChange={handleLimitChange}
page={paginationProps.page}
limit={paginationProps.limit}
total={paginationProps.total}
handleLimitChange={paginationProps.handleLimitChange}
/>
{booksResponse.status !== 200 ? (
<ErrorComponent message={'書籍情報を取得できませんでした。'} />
) : (
<BookCards books={booksResponse.data.books} />
)}
<PaginationComponent
totalNum={totalBook}
page={page}
limit={limit}
handlePaginationChange={handlePaginationChange}
total={paginationProps.total}
page={paginationProps.page}
limit={paginationProps.limit}
handlePaginationChange={paginationProps.handlePaginationChange}
/>
</Stack>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
import { Center, Pagination } from '@mantine/core';

interface PaginationComponentProps {
totalNum: number;
total: number;
page?: number;
limit?: number;
handlePaginationChange: (newPage: number) => void;
color?: string;
}

const PaginationComponent = ({
totalNum,
total,
page,
limit,
handlePaginationChange,
color,
}: PaginationComponentProps) => {
const limitNum = limit ?? 10;
const totalPage = totalNum / limitNum + 1;
const totalPage = total != 0 ? Math.ceil(total / limitNum) : 1;
return (
<Center>
<Pagination
Expand Down
15 changes: 4 additions & 11 deletions frontend/app/components/global-books/GlobalBookListComponent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,28 +9,21 @@ import ErrorComponent from '../common/error/ErrorComponent';
import GlobalBookCards from './GlobalBookCards';
import GlobalBookSearchComponent from './GlobalBookSearchComponent';
import PaginationComponent from '../common/pagination/PaginationComponent';
import { PaginationProps } from '~/types/paginatiion';

export interface HandleGlobalSearchFunctions {
handleDetailSubmit: (props: SearchBooksParams) => void;
handleKeywordSubmit: (props: SearchBooksParams) => void;
}

interface HandlePaginationProps {
handlePaginationChange: (newPage: number) => void;
handleLimitChange: (newLimit: number) => void;
page?: number;
limit?: number;
totalBook: number;
}

interface GlobalBookListComponentProps {
booksResponse?: searchBooksResponse;
form: UseFormReturnType<
SearchBooksParams,
(values: SearchBooksParams) => SearchBooksParams
>;
globalSearchFunctions: HandleGlobalSearchFunctions;
paginationProps: HandlePaginationProps;
paginationProps: PaginationProps;
isOpen: boolean;
open: () => void;
close: () => void;
Expand Down Expand Up @@ -63,7 +56,7 @@ const GlobalBookListComponent = ({
<ContentsHeader
page={paginationProps.page}
limit={paginationProps.limit}
total={paginationProps.totalBook}
total={paginationProps.total}
handleLimitChange={paginationProps.handleLimitChange}
/>
{!booksResponse ? (
Expand All @@ -74,7 +67,7 @@ const GlobalBookListComponent = ({
<GlobalBookCards books={booksResponse.data.books} />
)}
<PaginationComponent
totalNum={paginationProps.totalBook}
total={paginationProps.total}
page={paginationProps.page}
limit={paginationProps.limit}
handlePaginationChange={paginationProps.handlePaginationChange}
Expand Down
18 changes: 18 additions & 0 deletions frontend/app/components/users/NoUserComponent.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { Blockquote, Center } from '@mantine/core';
import { FaInfoCircle } from 'react-icons/fa';

interface NoUserComponentProps {
color?: string;
}

const NoUserComponent = ({ color }: NoUserComponentProps) => {
return (
<Center h="70dh" w="100%">
<Blockquote color={color ?? 'blue'} icon={<FaInfoCircle />} mt="xl">
ユーザーが存在しません。
</Blockquote>
</Center>
);
};

export default NoUserComponent;
19 changes: 19 additions & 0 deletions frontend/app/components/users/UserAddButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { Button } from '@mantine/core';
import { RiUserAddFill } from 'react-icons/ri';

const UserAddButton = () => {
return (
<Button
color="blue"
variant="filled"
radius="xl"
leftSection={<RiUserAddFill />}
component="a"
href="users/add"
>
ユーザー追加
</Button>
);
};

export default UserAddButton;
24 changes: 24 additions & 0 deletions frontend/app/components/users/UserDeleteButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { Button } from '@mantine/core';

interface UserDeleteButtonProps {
id: number;
handleDeleteUserButtonClick: (id: number) => void;
}

const UserDeleteButton = ({
id,
handleDeleteUserButtonClick,
}: UserDeleteButtonProps) => {
return (
<Button
color="red"
variant="light"
bd="solid 2px"
onClick={() => handleDeleteUserButtonClick(id)}
>
削除
</Button>
);
};

export default UserDeleteButton;
57 changes: 57 additions & 0 deletions frontend/app/components/users/UsersListComponent.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { Container, Stack } from '@mantine/core';
import UsersListTitle from './UsersListTitle';
import ContentsHeader from '../common/pagination/ContentsHeader';
import type { PaginationProps } from '~/types/paginatiion';
import PaginationComponent from '../common/pagination/PaginationComponent';
import ErrorComponent from '../common/error/ErrorComponent';
import { getUsersResponse } from 'client/client';
import UsersListTable from './UsersListTable';
import UserAddButton from './UserAddButton';

interface UsersListComponentProps {
paginationProps: PaginationProps;
usersResponse: getUsersResponse;
handleDeleteUserButtonClick: (id: number) => void;
}

const UsersListComponent = ({
paginationProps,
usersResponse,
handleDeleteUserButtonClick,
}: UsersListComponentProps) => {
return (
<Container>
<Stack
bg="var(--mantine-color-body)"
align="center"
justify="center"
maw="100%"
>
<UsersListTitle />
<ContentsHeader
page={paginationProps.page}
limit={paginationProps.limit}
total={paginationProps.total}
handleLimitChange={paginationProps.handleLimitChange}
/>
{usersResponse.status === 200 ? (
<UsersListTable
users={usersResponse.data.users}
handleDeleteUserButtonClick={handleDeleteUserButtonClick}
/>
) : (
<ErrorComponent message={'ユーザー情報を取得できませんでした。'} />
)}
<UserAddButton />
<PaginationComponent
total={paginationProps.total}
page={paginationProps.page}
limit={paginationProps.limit}
handlePaginationChange={paginationProps.handlePaginationChange}
/>
</Stack>
</Container>
);
};

export default UsersListComponent;
39 changes: 39 additions & 0 deletions frontend/app/components/users/UsersListTable.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { rem, Table } from '@mantine/core';
import { GetUsers200UsersItem } from 'client/client.schemas';
import UserDeleteButton from './UserDeleteButton';
import NoUserComponent from './NoUserComponent';

interface UsersTableProps {
users: GetUsers200UsersItem[];
handleDeleteUserButtonClick: (id: number) => void;
}

const UsersListTable = ({
users,
handleDeleteUserButtonClick,
}: UsersTableProps) => {
if (users.length === 0) return <NoUserComponent />;
return (
<Table striped maw="50%">
<Table.Tbody>
{users.map((user) => (
<Table.Tr key={user.id}>
{user.id && (
<>
<Table.Td>{user.name}</Table.Td>
<Table.Td maw={rem(5)}>
<UserDeleteButton
id={user.id}
handleDeleteUserButtonClick={handleDeleteUserButtonClick}
/>
</Table.Td>
</>
)}
</Table.Tr>
))}
</Table.Tbody>
</Table>
);
};

export default UsersListTable;
15 changes: 15 additions & 0 deletions frontend/app/components/users/UsersListTitle.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { Center, Group, Title } from '@mantine/core';
import { FaUsers } from 'react-icons/fa';

const UsersListTitle = () => {
return (
<Center>
<Group justify="center" align="center">
<FaUsers size="3.5ch" />
<Title order={1}>ユーザー一覧</Title>
</Group>
</Center>
);
};

export default UsersListTitle;
18 changes: 8 additions & 10 deletions frontend/app/routes/home._index/route.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { useEffect } from 'react';
import BookListComponent from '~/components/books/BookListComponent';
import { commitSession, getSession } from '~/services/session.server';
import { SelectedBookProps, selectedBooksAtom } from '~/stores/bookAtom';
import { ActionResponse } from '~/types/response';

interface LoaderData {
booksResponse: getBooksResponse;
Expand All @@ -26,11 +27,6 @@ interface LoaderData {
};
}

export interface ActionResponse {
method: string;
status: number;
}

export const loader = async ({ request }: LoaderFunctionArgs) => {
// 検索条件を取得する
const url = new URL(request.url);
Expand Down Expand Up @@ -263,11 +259,13 @@ const BooKListPage = () => {
isOpen={opened}
open={open}
close={close}
handlePaginationChange={handlePaginationChange}
handleLimitChange={handleLimitChange}
page={page ? Number(page) : undefined}
limit={limit ? Number(limit) : undefined}
totalBook={booksResponse.data.totalBook}
paginationProps={{
handlePaginationChange: handlePaginationChange,
handleLimitChange: handleLimitChange,
page: page ? Number(page) : undefined,
limit: limit ? Number(limit) : undefined,
total: booksResponse.data.totalBook,
}}
/>
);
};
Expand Down
6 changes: 1 addition & 5 deletions frontend/app/routes/home.books.$bookId/route.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,13 @@ import { commitSession, getSession } from '~/services/session.server';
import { Book } from 'client/client.schemas';
import BookDetailControlPanel from '~/components/book-detail/BookDetailControlPanel';
import ErrorComponent from '~/components/common/error/ErrorComponent';
import { ActionResponse } from '~/types/response';

interface LoaderData {
bookResponse: getBookResponse;
loansResponse?: getLoansResponse;
}

interface ActionResponse {
method: string;
status: number;
}

export interface BookDetailOutletContext {
book: Book;
loansResponse?: getLoansResponse;
Expand Down
2 changes: 1 addition & 1 deletion frontend/app/routes/home.global._index/route.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,7 @@ const GlobalBookListPage = () => {
handleLimitChange: handleLimitChange,
page: page ? Number(page) : undefined,
limit: limit ? Number(limit) : undefined,
totalBook: booksResponse ? booksResponse.data.totalBook : 0,
total: booksResponse ? booksResponse.data.totalBook : 0,
}}
searchMode={searchMode}
setSearchMode={setSearchMode}
Expand Down
Loading
Loading