|
1 | 1 | "use client"; |
2 | 2 |
|
3 | 3 | import { loadSalesFromEActivites } from "@/lib/crud/loadSalesFromEActivites"; |
4 | | -import { Button } from "@mantine/core"; |
5 | | -import React, { useTransition } from "react"; |
| 4 | +import { fetcher } from "@/lib/fetcher"; |
| 5 | +import { StatusReturn } from "@/lib/types"; |
| 6 | +import { Product } from "@docsoc/eactivities"; |
| 7 | +import { Alert, Box, Button, Checkbox, Group, Loader, Modal, Stack, Text } from "@mantine/core"; |
| 8 | +import { useDisclosure } from "@mantine/hooks"; |
| 9 | +import { RootItem } from "@prisma/client"; |
| 10 | +import React, { useCallback, useState, useTransition } from "react"; |
6 | 11 | import { FaSync } from "react-icons/fa"; |
| 12 | +import { FaUpRightFromSquare } from "react-icons/fa6"; |
| 13 | +import useSWR from "swr"; |
| 14 | + |
| 15 | +function CheckboxesForProducts({ close }: { close: () => void }) { |
| 16 | + const [value, setValue] = useState<string[]>([]); |
| 17 | + const [status, setStatus] = useState<StatusReturn>({ |
| 18 | + status: "pending", |
| 19 | + }); |
| 20 | + |
| 21 | + const { data: products, isLoading } = useSWR<RootItem[]>("/api/products/syncable", fetcher); |
7 | 22 |
|
8 | | -export const SyncEActivities = ({ |
9 | | - setActionsError, |
10 | | -}: { |
11 | | - setActionsError: (error: string | null) => void; |
12 | | -}) => { |
13 | 23 | const [isPending, startTransition] = useTransition(); |
14 | 24 |
|
15 | | - const syncEActivities = () => { |
16 | | - setActionsError(null); |
| 25 | + const syncEActivities = useCallback(() => { |
| 26 | + setStatus({ |
| 27 | + status: "pending", |
| 28 | + }); |
17 | 29 | startTransition(async () => { |
18 | | - const res = await loadSalesFromEActivites(); |
| 30 | + const res = await loadSalesFromEActivites( |
| 31 | + value.map((id) => parseInt(id, 10)).filter(isFinite), |
| 32 | + ); |
19 | 33 | if (res.status === "error") { |
20 | | - setActionsError(res.error); |
| 34 | + setStatus(res); |
| 35 | + } else { |
| 36 | + setStatus({ |
| 37 | + status: "success", |
| 38 | + }); |
| 39 | + close(); |
21 | 40 | } |
22 | 41 | }); |
23 | | - }; |
| 42 | + }, [close, value]); |
| 43 | + |
| 44 | + const cards = products?.map((product, i) => ( |
| 45 | + <Checkbox.Card radius="md" value={product.id.toString(10)} key={i} flex="1 0 0"> |
| 46 | + <Group wrap="nowrap" align="center" p="md"> |
| 47 | + <Checkbox.Indicator /> |
| 48 | + <Group flex="1 0 0"> |
| 49 | + <Box flex="1 0 0"> |
| 50 | + <Text> |
| 51 | + <b> |
| 52 | + <u>{product.name}</u> |
| 53 | + </b> |
| 54 | + </Text> |
| 55 | + <Text> |
| 56 | + <b>eActivites ID:</b> {product.eActivitiesId} |
| 57 | + </Text> |
| 58 | + <Text> |
| 59 | + <b>eActivites Name:</b> {product.eActivitiesName} |
| 60 | + </Text> |
| 61 | + </Box> |
| 62 | + {isLoading ? ( |
| 63 | + <Loader size="md" /> |
| 64 | + ) : ( |
| 65 | + product.eActivitiesURL && ( |
| 66 | + <Button |
| 67 | + component="a" |
| 68 | + href={product.eActivitiesURL} |
| 69 | + target="_blank" |
| 70 | + rightSection={<FaUpRightFromSquare />} |
| 71 | + > |
| 72 | + View on Union Shop |
| 73 | + </Button> |
| 74 | + ) |
| 75 | + )} |
| 76 | + </Group> |
| 77 | + </Group> |
| 78 | + </Checkbox.Card> |
| 79 | + )); |
| 80 | + |
| 81 | + return ( |
| 82 | + <Stack> |
| 83 | + { |
| 84 | + // Display error if there is one |
| 85 | + status.status === "error" && ( |
| 86 | + <Alert color="red" title="Error"> |
| 87 | + {status.error} |
| 88 | + </Alert> |
| 89 | + ) |
| 90 | + } |
| 91 | + <Checkbox.Group |
| 92 | + value={value} |
| 93 | + onChange={setValue} |
| 94 | + label="Select products to sync" |
| 95 | + description="If you are being IP banned, you might want to wait a few minutes and try fewer products" |
| 96 | + > |
| 97 | + <Stack pt="md" gap="xs"> |
| 98 | + {products && products.length > 0 ? cards : <Text>No products found</Text>} |
| 99 | + </Stack> |
| 100 | + </Checkbox.Group> |
| 101 | + |
| 102 | + <Group justify="space-between" mt="sm"> |
| 103 | + <Button |
| 104 | + onClick={() => |
| 105 | + setValue(products?.map((product) => product.id.toString(10)) ?? []) |
| 106 | + } |
| 107 | + color="violet" |
| 108 | + loading={false} |
| 109 | + > |
| 110 | + Select all |
| 111 | + </Button> |
| 112 | + <Button onClick={syncEActivities} color="green" loading={isPending}> |
| 113 | + Sync {value.length} products |
| 114 | + </Button> |
| 115 | + </Group> |
| 116 | + </Stack> |
| 117 | + ); |
| 118 | +} |
| 119 | + |
| 120 | +export const SyncEActivities = ({ |
| 121 | + setActionsError, |
| 122 | +}: { |
| 123 | + setActionsError: (error: string | null) => void; |
| 124 | +}) => { |
| 125 | + const [opened, { open, close }] = useDisclosure(false); |
24 | 126 |
|
25 | 127 | return ( |
26 | | - <Button |
27 | | - leftSection={<FaSync />} |
28 | | - color="violet" |
29 | | - loading={isPending} |
30 | | - onClick={syncEActivities} |
31 | | - > |
32 | | - Sync from eActivities |
33 | | - </Button> |
| 128 | + <> |
| 129 | + <Modal opened={opened} onClose={close} title={`Select products to sync`} size="xl"> |
| 130 | + <CheckboxesForProducts close={close} /> |
| 131 | + </Modal> |
| 132 | + <Button leftSection={<FaSync />} color="violet" onClick={open}> |
| 133 | + Sync from eActivities |
| 134 | + </Button> |
| 135 | + </> |
34 | 136 | ); |
35 | 137 | }; |
0 commit comments