-
Notifications
You must be signed in to change notification settings - Fork 0
カートページの実装 #133
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
カートページの実装 #133
Changes from all commits
c69a3fc
a6caf3b
ffcf996
17bcfc3
d543153
569de83
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| import { Card } from '@mantine/core'; | ||
| import { CartProps } from '~/stores/cartAtom'; | ||
| import BookCardThumbnail from '../books/BookCardThumbnail'; | ||
| import CartCardHeader from './CartCardHeader'; | ||
|
|
||
| interface CartCardProps { | ||
| book: CartProps; | ||
| } | ||
|
|
||
| const CartCard = ({ book }: CartCardProps) => { | ||
| return ( | ||
| <Card shadow="sm" radius="md" pb="xs" withBorder> | ||
| <Card.Section withBorder inheritPadding> | ||
| <CartCardHeader | ||
| id={book.id} | ||
| stock={book.stock} | ||
| volume={book.volume} | ||
| thumbnail={book.thumbnail} | ||
| /> | ||
| </Card.Section> | ||
| <Card.Section withBorder inheritPadding py="xs"> | ||
| <BookCardThumbnail id={book.id} thumbnail={book.thumbnail} /> | ||
| </Card.Section> | ||
| </Card> | ||
| ); | ||
| }; | ||
|
|
||
| export default CartCard; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,77 @@ | ||
| import { Checkbox, Group } from '@mantine/core'; | ||
| import { useAtom } from 'jotai'; | ||
| import { cartAtom, CartProps, selectedCartBooksAtom } from '~/stores/cartAtom'; | ||
| import CartCardNumberInput from './CartCardNumberInput'; | ||
|
|
||
| interface CartCardHeaderProps { | ||
| id: number; | ||
| stock: number; | ||
| volume: number; | ||
| thumbnail?: string; | ||
| } | ||
|
|
||
| const CartCardHeader = ({ | ||
| id, | ||
| stock, | ||
| volume, | ||
| thumbnail, | ||
| }: CartCardHeaderProps) => { | ||
| const [cart, setCart] = useAtom(cartAtom); | ||
| const [selectedCartBook, setSelectedCartBook] = useAtom( | ||
| selectedCartBooksAtom, | ||
| ); | ||
|
|
||
| // 該当する本のvolumeを変更する | ||
| const handleChangeVolume = (id: number, value: number) => { | ||
| setCart( | ||
| cart.map((element) => { | ||
| if (element.id === id) { | ||
| return { | ||
| id: element.id, | ||
| stock: element.stock, | ||
| thumbnail: element.thumbnail, | ||
| volume: value, | ||
| }; | ||
| } | ||
| return element; | ||
| }), | ||
| ); | ||
| }; | ||
|
|
||
| // 選択されている本のIDと表示する本のIDを比較する関数 | ||
| const isSelected = (element: CartProps) => element.id === id; | ||
|
|
||
| const switchBookSelect = () => { | ||
| // チェックボックスの状態が変化した時に | ||
| if (selectedCartBook.some(isSelected)) { | ||
| // すでに選択されていた場合は選択を外す | ||
| setSelectedCartBook( | ||
| selectedCartBook.filter((element) => element.id !== id), | ||
| ); | ||
| } else { | ||
| // 選択されていなかった場合は選択する | ||
| setSelectedCartBook([ | ||
| ...selectedCartBook, | ||
| { id, stock, thumbnail, volume: 1 }, | ||
| ]); | ||
| } | ||
| }; | ||
|
|
||
| return ( | ||
| <Group justify="space-between" py={10}> | ||
| <Checkbox | ||
| value={id} | ||
| checked={selectedCartBook.some(isSelected)} | ||
| onChange={switchBookSelect} | ||
| /> | ||
| <CartCardNumberInput | ||
| id={id} | ||
| stock={stock} | ||
| volume={volume} | ||
| handleChangeVolume={handleChangeVolume} | ||
| /> | ||
| </Group> | ||
| ); | ||
| }; | ||
|
|
||
| export default CartCardHeader; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,40 @@ | ||
| import { Group, Select, Text } from '@mantine/core'; | ||
| import { range } from '@mantine/hooks'; | ||
|
|
||
| interface CartCardHeaderBadgeProps { | ||
| id: number; | ||
| stock: number; | ||
| volume: number; | ||
| handleChangeVolume: (id: number, value: number) => void; | ||
| } | ||
|
|
||
| const CartCardNumberInput = ({ | ||
| id, | ||
| stock, | ||
| volume, | ||
| handleChangeVolume, | ||
| }: CartCardHeaderBadgeProps) => { | ||
| const stockList = range(0, stock); | ||
| const dataList = stock >= volume ? stockList : [...stockList, volume]; | ||
| const strList = dataList.map((data) => data.toString()); | ||
|
|
||
| const handleOnChange = (volume: string | null) => { | ||
| if (!volume) return; | ||
| const numVolume = Number(volume); | ||
| handleChangeVolume(id, numVolume); | ||
| }; | ||
| return ( | ||
| <Group justify="flex-end" w="70%"> | ||
| <Text>冊数</Text> | ||
| <Select | ||
| w="50%" | ||
| data={strList} | ||
| value={String(volume)} | ||
| error={volume > stock} | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 便利だね
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. やったあ |
||
| onChange={(value) => handleOnChange(value)} | ||
| /> | ||
| </Group> | ||
| ); | ||
| }; | ||
|
|
||
| export default CartCardNumberInput; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| import { ScrollArea, SimpleGrid } from '@mantine/core'; | ||
| import { useAtom } from 'jotai'; | ||
| import { cartAtom } from '~/stores/cartAtom'; | ||
| import CartCard from './CartCard'; | ||
|
|
||
| const CartCards = () => { | ||
| const [cart] = useAtom(cartAtom); | ||
|
|
||
| return ( | ||
| <ScrollArea h="70dh"> | ||
| <SimpleGrid | ||
| type="container" | ||
| cols={{ | ||
| base: 2, | ||
| '500px': 3, | ||
| '800px': 4, | ||
| '1100px': 5, | ||
| '1400px': 6, | ||
| '1700px': 7, | ||
| }} | ||
| // 画面幅が300pxを超えた場合、カードの間をxlにする | ||
| spacing={{ base: 10, '300px': 'xl' }} | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 画面幅が300ピクセル以上の場合に xl サイズの間隔が適用されると理解した.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. コメント残しました |
||
| > | ||
| {cart.map((book, index) => ( | ||
| <CartCard key={index} book={book} /> | ||
| ))} | ||
| </SimpleGrid> | ||
| </ScrollArea> | ||
| ); | ||
| }; | ||
|
|
||
| export default CartCards; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| import { Stack } from '@mantine/core'; | ||
| import CartTitle from './CartTitle'; | ||
| import CartCards from './CartCards'; | ||
| import CartSelectedDialog from './CartSelectedDialog'; | ||
| import { useAtom } from 'jotai'; | ||
| import { cartAtom } from '~/stores/cartAtom'; | ||
| import NoCartComponent from './NoCartComponent'; | ||
|
|
||
| interface CartListComponentProps { | ||
| handleBorrowButtonClick: () => void; | ||
| } | ||
|
|
||
| const CartListComponent = ({ | ||
| handleBorrowButtonClick, | ||
| }: CartListComponentProps) => { | ||
| const [cart] = useAtom(cartAtom); | ||
| return ( | ||
| <Stack bg="var(--mantine-color-body)" align="stretch" justify="flex-start"> | ||
| <CartTitle /> | ||
| {cart.length == 0 ? ( | ||
| <NoCartComponent /> | ||
| ) : ( | ||
| <> | ||
| <CartCards /> | ||
| <CartSelectedDialog | ||
| handleBorrowButtonClick={handleBorrowButtonClick} | ||
| /> | ||
| </> | ||
| )} | ||
| </Stack> | ||
| ); | ||
| }; | ||
|
|
||
| export default CartListComponent; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
この3つは何のための変数だろう?
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
もし、volumeをstockが超えてたら0 ~ stock, volumeの要素を持つ配列が選択肢になる。
そうでないなら0 ~ stockまでを選択肢とする
そういった選択肢の配列