Compare commits
62 Commits
bbc3adf99c
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
017ce48835
|
|||
|
72f8791276
|
|||
|
63b1926056
|
|||
|
25dc50e05c
|
|||
|
a403832735
|
|||
|
e1f1093d84
|
|||
|
243a4d1ceb
|
|||
|
54d9bd5e82
|
|||
|
a1f4b4eabe
|
|||
|
64edc6169b
|
|||
|
cf84722418
|
|||
|
102b29c54f
|
|||
|
42f13612b1
|
|||
|
b1448ac30e
|
|||
|
bd053908a4
|
|||
|
cae1b523f5
|
|||
|
e4b31efa72
|
|||
|
5d249a7069
|
|||
|
56c5e6dc0f
|
|||
|
f2c332b649
|
|||
|
b8bc4acf4b
|
|||
|
5bb538c790
|
|||
|
7aa1d27844
|
|||
|
3c5c51b5da
|
|||
|
74c0e52a80
|
|||
|
7b68f14c2e
|
|||
|
85871fc90a
|
|||
|
41f361fcf1
|
|||
|
513234bbe6
|
|||
|
5ba59ff596
|
|||
|
bcd07299c5
|
|||
|
7c7701f406
|
|||
|
fcf3c95a0a
|
|||
|
398b2a938a
|
|||
|
fe64e33c1d
|
|||
|
edc392fba0
|
|||
|
62319a84d1
|
|||
|
195af5e124
|
|||
|
f9d9bdbac6
|
|||
|
451d1c93d4
|
|||
|
157c9b188b
|
|||
|
8d357ec249
|
|||
|
ba8e1bab7c
|
|||
|
68898ba654
|
|||
|
44ab73c8a5
|
|||
|
98c662ed9b
|
|||
|
3d8ce8356f
|
|||
|
8c32cd121d
|
|||
|
6d8238f394
|
|||
|
c2c6924c8f
|
|||
|
ba077e1c05
|
|||
|
e6424024d1
|
|||
|
51d1121b23
|
|||
|
31d48ee326
|
|||
|
03d6a47cb7
|
|||
|
0b2dd8fb6c
|
|||
|
e7015e8549
|
|||
|
08b36c04b8
|
|||
|
6730b876bf
|
|||
|
c48ca6fc24
|
|||
|
2245b040c6
|
|||
|
cb6c835575
|
@@ -1 +1 @@
|
||||
v22.13.1
|
||||
v22.20.0
|
||||
|
||||
@@ -7,7 +7,7 @@ Please don't complain about your ban on this repo.
|
||||
|
||||
## Get the Code
|
||||
|
||||
`git clone https://teamhydra.io/regalijan/car-crushers-portal.git`
|
||||
`git clone https://git.hep.gg/regalijan/car-crushers-portal.git`
|
||||
|
||||
## Make it Larger
|
||||
|
||||
|
||||
@@ -37,7 +37,6 @@ export default function () {
|
||||
const toast = useToast();
|
||||
const currentDate = new Date();
|
||||
const currentMonth = currentDate.getUTCMonth() + 1;
|
||||
const currentYear = currentDate.getUTCFullYear();
|
||||
const [datePickerMax, setDatePickerMax] = useState("");
|
||||
const [datePickerMin, setDatePickerMin] = useState("");
|
||||
const [eventDay, setEventDay] = useState("0");
|
||||
@@ -47,13 +46,10 @@ export default function () {
|
||||
const [submitSuccess, setSubmitSuccess] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
setDatePickerMin(
|
||||
`${currentYear}-${currentMonth.toString().padStart(2, "0")}-${currentDate.getUTCDate().toString().padStart(2, "0")}`,
|
||||
);
|
||||
setDatePickerMin(`${new Date().toISOString().split("T").at(0)}`);
|
||||
currentDate.setUTCMonth(currentMonth);
|
||||
currentDate.setUTCDate(0);
|
||||
setDatePickerMax(
|
||||
`${currentYear}-${currentMonth.toString().padStart(2, "0")}-${new Date(currentYear, currentMonth, 0).getUTCDate()}`,
|
||||
);
|
||||
setDatePickerMax(`${currentDate.toISOString().split("T").at(0)}`);
|
||||
}, []);
|
||||
|
||||
async function submit() {
|
||||
|
||||
@@ -348,7 +348,18 @@ export default function () {
|
||||
const newDate = (
|
||||
document.getElementById("reschedule-input") as HTMLInputElement
|
||||
).value;
|
||||
const day = newDate.split("-").at(2);
|
||||
const day = parseInt(newDate.split("-").at(2) ?? "");
|
||||
|
||||
if (isNaN(day)) {
|
||||
toast({
|
||||
description: "Please select a date, then try again.",
|
||||
status: "error",
|
||||
title: "No date selected",
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const rescheduleResp = await fetch(`/api/events-team/events/${eventId}`, {
|
||||
body: JSON.stringify({ day }),
|
||||
headers: {
|
||||
|
||||
@@ -175,6 +175,7 @@ export default function () {
|
||||
<NumberInput
|
||||
defaultValue={year}
|
||||
max={new Date().getUTCFullYear()}
|
||||
onChange={(_, value) => setYear(value)}
|
||||
precision={0}
|
||||
>
|
||||
<NumberInputField />
|
||||
|
||||
@@ -76,12 +76,15 @@ export async function loader({ context }: { context: RequestContext }) {
|
||||
|
||||
for (const member of Object.keys(memberMap))
|
||||
if (
|
||||
memberMap[member].points < 30 &&
|
||||
(memberMap[member].points < 50 ||
|
||||
eventsQuery.results.filter(
|
||||
(e) => e.type === "gamenight" && e.created_by === member,
|
||||
).length === 0) &&
|
||||
!inactivityQuery.results.find(
|
||||
(i) => i.uid === member && JSON.parse(i.decisions).et,
|
||||
)
|
||||
)
|
||||
memberMap[member].points -= 30;
|
||||
memberMap[member].points -= 50;
|
||||
|
||||
return {
|
||||
members: memberMap,
|
||||
|
||||
209
app/routes/gmm.tsx
Normal file
209
app/routes/gmm.tsx
Normal file
@@ -0,0 +1,209 @@
|
||||
import {
|
||||
Button,
|
||||
Container,
|
||||
FormControl,
|
||||
FormLabel,
|
||||
Input,
|
||||
Modal,
|
||||
ModalBody,
|
||||
ModalCloseButton,
|
||||
ModalContent,
|
||||
ModalFooter,
|
||||
ModalHeader,
|
||||
ModalOverlay,
|
||||
Table,
|
||||
TableCaption,
|
||||
TableContainer,
|
||||
Tbody,
|
||||
Td,
|
||||
Th,
|
||||
Thead,
|
||||
Tr,
|
||||
useDisclosure,
|
||||
useToast,
|
||||
} from "@chakra-ui/react";
|
||||
import { useLoaderData } from "@remix-run/react";
|
||||
import { useState } from "react";
|
||||
|
||||
export async function loader({ context }: { context: RequestContext }) {
|
||||
if (!context.data.current_user)
|
||||
throw new Response(null, {
|
||||
status: 401,
|
||||
});
|
||||
|
||||
if (
|
||||
![
|
||||
"165594923586945025",
|
||||
"289372404541554689",
|
||||
"396347223736057866",
|
||||
].includes(context.data.current_user.id)
|
||||
)
|
||||
throw new Response(null, {
|
||||
status: 403,
|
||||
});
|
||||
|
||||
return (await context.env.DATA.list({ prefix: "gamemod_" }))?.keys ?? [];
|
||||
}
|
||||
|
||||
export default function () {
|
||||
const data: { [k: string]: any }[] = useLoaderData<typeof loader>();
|
||||
const [gameModData, setGameModData] = useState(data);
|
||||
const { isOpen, onClose, onOpen } = useDisclosure();
|
||||
const [idToAdd, setIdToAdd] = useState<string>("");
|
||||
const [nameToAdd, setNameToAdd] = useState<string>("");
|
||||
const toast = useToast();
|
||||
|
||||
async function addMod(id: string, name: string) {
|
||||
const response = await fetch("/api/gme/add", {
|
||||
body: JSON.stringify({ name, user: id }),
|
||||
headers: {
|
||||
"content-type": "application/json",
|
||||
},
|
||||
method: "POST",
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
let msg = "Unknown error";
|
||||
|
||||
try {
|
||||
msg = ((await response.json()) as { error: string }).error;
|
||||
} catch {}
|
||||
|
||||
toast({
|
||||
description: msg,
|
||||
status: "error",
|
||||
title: "Cannot add game mod",
|
||||
});
|
||||
} else {
|
||||
onClose();
|
||||
location.reload();
|
||||
}
|
||||
|
||||
setIdToAdd("");
|
||||
setNameToAdd("");
|
||||
}
|
||||
|
||||
async function removeMod(user: string) {
|
||||
const response = await fetch("/api/gme/remove", {
|
||||
body: JSON.stringify({ user }),
|
||||
headers: {
|
||||
"content-type": "application/json",
|
||||
},
|
||||
method: "POST",
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
let msg = "Unknown error";
|
||||
|
||||
try {
|
||||
msg = ((await response.json()) as { error: string }).error;
|
||||
} catch {}
|
||||
toast({
|
||||
description: msg,
|
||||
status: "error",
|
||||
title: "Cannot remove game mod",
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
toast({
|
||||
description: `${data.find((i) => i.metadata.id === user)?.name} was removed as a game mod`,
|
||||
status: "success",
|
||||
title: "Game mod removed",
|
||||
});
|
||||
|
||||
setGameModData(gameModData.filter((i) => i.metadata.id !== user));
|
||||
}
|
||||
|
||||
return (
|
||||
<Container maxW="container.lg">
|
||||
<TableContainer>
|
||||
<Table variant="simple">
|
||||
<TableCaption>Currently active game mods</TableCaption>
|
||||
<Thead>
|
||||
<Tr>
|
||||
<Th>ID</Th>
|
||||
<Th>Name</Th>
|
||||
<Th>Added At</Th>
|
||||
<Th>Added By</Th>
|
||||
<Th>Remove</Th>
|
||||
</Tr>
|
||||
</Thead>
|
||||
<Tbody>
|
||||
{gameModData.map((item) => {
|
||||
return (
|
||||
<Tr key={item.metadata.id}>
|
||||
<Td>{item.metadata.id}</Td>
|
||||
<Td>{item.metadata.name}</Td>
|
||||
<Td>{item.metadata.created_at}</Td>
|
||||
<Td>{item.metadata.created_by}</Td>
|
||||
<Td>
|
||||
<Button
|
||||
onClick={async () => await removeMod(item.metadata.id)}
|
||||
>
|
||||
Remove
|
||||
</Button>
|
||||
</Td>
|
||||
</Tr>
|
||||
);
|
||||
})}
|
||||
</Tbody>
|
||||
</Table>
|
||||
</TableContainer>
|
||||
<Button alignSelf="end" mt="16px" onClick={onOpen}>
|
||||
Add
|
||||
</Button>
|
||||
<Modal isOpen={isOpen} onClose={onClose}>
|
||||
<ModalOverlay />
|
||||
<ModalContent>
|
||||
<ModalHeader>Add Game Mod</ModalHeader>
|
||||
<ModalCloseButton />
|
||||
<ModalBody>
|
||||
<FormControl>
|
||||
<FormLabel>Name</FormLabel>
|
||||
<Input
|
||||
maxLength={32}
|
||||
onChange={(e) => setNameToAdd(e.target.value)}
|
||||
value={nameToAdd}
|
||||
/>
|
||||
</FormControl>
|
||||
<br />
|
||||
<FormControl pt="16px">
|
||||
<FormLabel>ID</FormLabel>
|
||||
<Input
|
||||
maxLength={19}
|
||||
onChange={(e) => setIdToAdd(e.target.value)}
|
||||
value={idToAdd}
|
||||
/>
|
||||
</FormControl>
|
||||
</ModalBody>
|
||||
<ModalFooter gap="8px">
|
||||
<Button
|
||||
onClick={() => {
|
||||
onClose();
|
||||
setIdToAdd("");
|
||||
setNameToAdd("");
|
||||
}}
|
||||
>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button
|
||||
colorScheme="blue"
|
||||
disabled={
|
||||
!idToAdd.match(/\d{17,19}/) ||
|
||||
nameToAdd.length < 1 ||
|
||||
nameToAdd.length > 32
|
||||
}
|
||||
onClick={async () => {
|
||||
await addMod(idToAdd, nameToAdd);
|
||||
}}
|
||||
>
|
||||
Add
|
||||
</Button>
|
||||
</ModalFooter>
|
||||
</ModalContent>
|
||||
</Modal>
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
@@ -7,6 +7,7 @@ import {
|
||||
ModalBody,
|
||||
ModalCloseButton,
|
||||
ModalContent,
|
||||
ModalFooter,
|
||||
ModalHeader,
|
||||
ModalOverlay,
|
||||
Table,
|
||||
@@ -69,19 +70,22 @@ export async function loader({ context }: { context: RequestContext }) {
|
||||
results[i].user = JSON.parse(results[i].user as string);
|
||||
}
|
||||
|
||||
return results.filter((row) => {
|
||||
const decisionValues = Object.values(
|
||||
row.decisions as { [k: string]: boolean },
|
||||
);
|
||||
return {
|
||||
can_delete: currentUser.permissions & (1 << 0),
|
||||
results: results.filter((row) => {
|
||||
const decisionValues = Object.values(
|
||||
row.decisions as { [k: string]: boolean },
|
||||
);
|
||||
|
||||
return decisionValues.find((d) => d);
|
||||
}) as unknown as {
|
||||
decisions: { [k: string]: boolean };
|
||||
end: string;
|
||||
id: string;
|
||||
start: string;
|
||||
user: { email?: string; id: string; username: string };
|
||||
}[];
|
||||
return decisionValues.find((d) => d);
|
||||
}) as unknown as {
|
||||
decisions: { [k: string]: boolean };
|
||||
end: string;
|
||||
id: string;
|
||||
start: string;
|
||||
user: { email?: string; id: string; username: string };
|
||||
}[],
|
||||
};
|
||||
}
|
||||
|
||||
export default function () {
|
||||
@@ -115,6 +119,35 @@ export default function () {
|
||||
onOpen();
|
||||
}
|
||||
|
||||
async function deleteInactivity(id: string) {
|
||||
const response = await fetch(`/api/inactivity/${id}`, {
|
||||
method: "DELETE",
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
onClose();
|
||||
setInactivity({});
|
||||
toast({
|
||||
status: "success",
|
||||
title: "Notice Deleted",
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
let msg = "Unknown error";
|
||||
|
||||
try {
|
||||
msg = ((await response.json()) as { error: string }).error;
|
||||
} catch {}
|
||||
|
||||
toast({
|
||||
description: msg,
|
||||
status: "error",
|
||||
title: "Failed to Delete",
|
||||
});
|
||||
}
|
||||
|
||||
return (
|
||||
<Container maxW="container.lg">
|
||||
<Modal isOpen={isOpen} onClose={onClose}>
|
||||
@@ -136,23 +169,30 @@ export default function () {
|
||||
Decisions:
|
||||
<br />
|
||||
Approved:
|
||||
{Object.keys(currentInactivity.decisions ?? {}).filter(
|
||||
(d) => currentInactivity.decisions[d],
|
||||
)}
|
||||
{Object.keys(currentInactivity.decisions ?? {})
|
||||
.filter((d) => currentInactivity.decisions[d])
|
||||
.join(", ")}
|
||||
<br />
|
||||
Denied:
|
||||
{Object.keys(currentInactivity.decisions ?? {}).filter(
|
||||
(d) => !currentInactivity.decisions[d],
|
||||
)}
|
||||
{Object.keys(currentInactivity.decisions ?? {})
|
||||
.filter((d) => !currentInactivity.decisions[d])
|
||||
.join(", ")}
|
||||
<br />
|
||||
Pending:
|
||||
{currentInactivity.departments?.filter(
|
||||
(d: "DM" | "ET" | "FM" | "WM") =>
|
||||
typeof currentInactivity.decisions[d] === "undefined",
|
||||
)}
|
||||
{currentInactivity.departments
|
||||
?.filter(
|
||||
(d: "DM" | "ET" | "FM" | "WM") =>
|
||||
typeof currentInactivity.decisions[d] === "undefined",
|
||||
)
|
||||
.join(", ")}
|
||||
</ListItem>
|
||||
</UnorderedList>
|
||||
</ModalBody>
|
||||
{data.can_delete ? (
|
||||
<ModalFooter>
|
||||
<Button colorScheme="red">Delete</Button>
|
||||
</ModalFooter>
|
||||
) : null}
|
||||
</ModalContent>
|
||||
</Modal>
|
||||
<Heading pb="32px">Current Inactivity Notices</Heading>
|
||||
@@ -171,7 +211,7 @@ export default function () {
|
||||
</Tr>
|
||||
</Thead>
|
||||
<Tbody>
|
||||
{data.map((row) => (
|
||||
{data.results.map((row) => (
|
||||
<Tr key={row.id}>
|
||||
<Td>{row.user.username}</Td>
|
||||
<Td>{row.user.id}</Td>
|
||||
|
||||
@@ -30,7 +30,6 @@ import { useLoaderData } from "@remix-run/react";
|
||||
import AppealBans from "../../components/AppealBans.js";
|
||||
import AppealCard from "../../components/AppealCard.js";
|
||||
import GameAppealCard from "../../components/GameAppealCard.js";
|
||||
import GameModManagementModal from "../../components/GameModManagementModal.js";
|
||||
import NewGameBan from "../../components/NewGameBan.js";
|
||||
import NewInfractionModal from "../../components/NewInfractionModal.js";
|
||||
import ReportCard from "../../components/ReportCard.js";
|
||||
@@ -151,7 +150,7 @@ export default function () {
|
||||
|
||||
useEffect(() => {
|
||||
if (messageChannel.current) {
|
||||
messageChannel.current.port1.onmessage = function (ev) {
|
||||
messageChannel.current.port1.onmessage = function (ev: any) {
|
||||
const { data }: { data: string } = ev;
|
||||
|
||||
setEntries([...entries].filter((entry) => entry.id !== data));
|
||||
@@ -337,7 +336,11 @@ export default function () {
|
||||
},
|
||||
appeal_bans: useDisclosure(),
|
||||
game_ban: useDisclosure(),
|
||||
gme: useDisclosure(),
|
||||
gme: {
|
||||
isOpen: false,
|
||||
onClose: () => {},
|
||||
onOpen: () => location.assign("/gmm"),
|
||||
},
|
||||
inactivity: useDisclosure(),
|
||||
infraction: useDisclosure(),
|
||||
user_lookup: {
|
||||
@@ -431,10 +434,6 @@ export default function () {
|
||||
isOpen={itemModals.appeal_bans.isOpen}
|
||||
onClose={itemModals.appeal_bans.onClose}
|
||||
/>
|
||||
<GameModManagementModal
|
||||
isOpen={itemModals.gme.isOpen}
|
||||
onClose={itemModals.gme.onClose}
|
||||
/>
|
||||
<NewGameBan
|
||||
isOpen={itemModals.game_ban.isOpen}
|
||||
onClose={itemModals.game_ban.onClose}
|
||||
|
||||
@@ -9,6 +9,9 @@ import {
|
||||
HStack,
|
||||
Input,
|
||||
Link,
|
||||
Radio,
|
||||
RadioGroup,
|
||||
Stack,
|
||||
Text,
|
||||
Textarea,
|
||||
useToast,
|
||||
@@ -31,28 +34,34 @@ export async function loader({
|
||||
export function meta() {
|
||||
return [
|
||||
{
|
||||
title: "Report an Exploiter - Car Crushers",
|
||||
title: "Send a Report - Car Crushers",
|
||||
},
|
||||
{
|
||||
name: "description",
|
||||
content: "Use this page to report a cheater",
|
||||
content: "Use this page to submit a report",
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
export default function () {
|
||||
const [fileProgress, setFileProgress] = useState(0);
|
||||
const [submissionType, setSubmissionType] = useState("exploit");
|
||||
const [showSuccess, setShowSuccess] = useState(false);
|
||||
const toast = useToast();
|
||||
const [uploading, setUploading] = useState(false);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const fileTypes: { [k: string]: string } = {
|
||||
avif: "image/avif",
|
||||
gif: "image/gif",
|
||||
jpg: "image/jpeg",
|
||||
jpeg: "image/jpeg",
|
||||
m4v: "video/x-m4v",
|
||||
mkv: "video/x-matroska",
|
||||
mov: "video/mp4",
|
||||
mp4: "video/mp4",
|
||||
png: "image/png",
|
||||
webm: "video/webm",
|
||||
webp: "image/webp",
|
||||
wmv: "video/x-ms-wmv",
|
||||
};
|
||||
|
||||
@@ -132,6 +141,7 @@ export default function () {
|
||||
body: JSON.stringify({
|
||||
description: description || undefined,
|
||||
files: filelist,
|
||||
submissionType,
|
||||
turnstileResponse: logged_in ? undefined : turnstileToken,
|
||||
usernames,
|
||||
}),
|
||||
@@ -276,6 +286,19 @@ export default function () {
|
||||
</FormLabel>
|
||||
<Input id="usernames" placeholder="builderman" />
|
||||
</FormControl>
|
||||
<FormControl isRequired>
|
||||
<FormLabel htmlFor="submissionType">Type of Report</FormLabel>
|
||||
<RadioGroup
|
||||
id="submissionType"
|
||||
onChange={setSubmissionType}
|
||||
value={submissionType}
|
||||
>
|
||||
<Stack spacing={2}>
|
||||
<Radio value="exploit">Exploiter</Radio>
|
||||
<Radio value="abuse">Server Configurator Abuse</Radio>
|
||||
</Stack>
|
||||
</RadioGroup>
|
||||
</FormControl>
|
||||
<br />
|
||||
<FormControl isRequired>
|
||||
<FormLabel>Your Evidence (Max size per file: 512MB)</FormLabel>
|
||||
|
||||
@@ -22,7 +22,7 @@ import NewAppealBan from "./NewAppealBan.js";
|
||||
|
||||
export default function (props: { isOpen: boolean; onClose: () => void }) {
|
||||
const [entries, setEntries] = useState(
|
||||
[] as { created_at: number; created_by: string; user: string }[],
|
||||
[] as { created_at: number | string; created_by: string; user: string }[],
|
||||
);
|
||||
const toast = useToast();
|
||||
const { isOpen, onClose, onOpen } = useDisclosure();
|
||||
@@ -61,7 +61,15 @@ export default function (props: { isOpen: boolean; onClose: () => void }) {
|
||||
setEntries([...entries].filter((entry) => entry.user !== user));
|
||||
}
|
||||
|
||||
useEffect(() => {}, []);
|
||||
useEffect(() => {
|
||||
(async function () {
|
||||
const banData = await fetch("/api/appeals/bans");
|
||||
|
||||
if (!banData.ok) return;
|
||||
|
||||
setEntries(await banData.json());
|
||||
})();
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<>
|
||||
|
||||
@@ -76,6 +76,8 @@ export default function (props: AppealCardProps & { port?: MessagePort }) {
|
||||
}
|
||||
|
||||
onClose();
|
||||
setFeedback("");
|
||||
setAction("");
|
||||
setLoading(false);
|
||||
props.port?.postMessage(`appeal_${props.id}`);
|
||||
}
|
||||
|
||||
@@ -84,6 +84,10 @@ export default function (props: GameAppealProps & { port?: MessagePort }) {
|
||||
</CardHeader>
|
||||
<CardBody>
|
||||
<Stack divider={<StackDivider />}>
|
||||
<Box>
|
||||
<Heading size="xs">Appeal Type</Heading>
|
||||
<Text>{props.type}</Text>
|
||||
</Box>
|
||||
<Box>
|
||||
<Heading size="xs">Response: Explanation of Ban</Heading>
|
||||
<Text>{props.what_happened}</Text>
|
||||
|
||||
@@ -1,157 +0,0 @@
|
||||
import {
|
||||
Button,
|
||||
HStack,
|
||||
Input,
|
||||
Link,
|
||||
Modal,
|
||||
ModalBody,
|
||||
ModalCloseButton,
|
||||
ModalContent,
|
||||
ModalHeader,
|
||||
ModalOverlay,
|
||||
Table,
|
||||
TableContainer,
|
||||
Tbody,
|
||||
Td,
|
||||
Th,
|
||||
Thead,
|
||||
Tr,
|
||||
useToast,
|
||||
} from "@chakra-ui/react";
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
export default function (props: { isOpen: boolean; onClose: () => void }) {
|
||||
const [mods, setMods] = useState([]);
|
||||
const [userToAdd, setUserToAdd] = useState("");
|
||||
const toast = useToast();
|
||||
|
||||
useEffect(() => {
|
||||
if (!props.isOpen) return;
|
||||
|
||||
(async function () {
|
||||
const gmeResp = await fetch("/api/gme/list");
|
||||
|
||||
if (!gmeResp.ok) {
|
||||
toast({
|
||||
description: "Failed to load GME data",
|
||||
status: "error",
|
||||
title: "Oops",
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
setMods(await gmeResp.json());
|
||||
})();
|
||||
}, [props.isOpen]);
|
||||
|
||||
async function addUser() {
|
||||
if (!userToAdd || !userToAdd.match(/^\d{17,19}$/)) {
|
||||
toast({
|
||||
description: "Please check your input and try again",
|
||||
status: "error",
|
||||
title: "Invalid user",
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const addResp = await fetch("/api/gme/add", {
|
||||
body: JSON.stringify({ user: userToAdd }),
|
||||
headers: {
|
||||
"content-type": "application/json",
|
||||
},
|
||||
method: "POST",
|
||||
});
|
||||
|
||||
if (!addResp.ok) {
|
||||
toast({
|
||||
description: ((await addResp.json()) as { error: string }).error,
|
||||
status: "error",
|
||||
title: "Oops",
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
toast({
|
||||
description: `User ${userToAdd} added`,
|
||||
status: "success",
|
||||
title: "Success",
|
||||
});
|
||||
|
||||
props.onClose();
|
||||
}
|
||||
|
||||
async function removeUser(user: string) {
|
||||
const removeResp = await fetch("/api/gme/remove", {
|
||||
body: JSON.stringify({ user }),
|
||||
headers: {
|
||||
"content-type": "application/json",
|
||||
},
|
||||
method: "POST",
|
||||
});
|
||||
|
||||
if (!removeResp.ok) {
|
||||
toast({
|
||||
description: ((await removeResp.json()) as { error: string }).error,
|
||||
status: "error",
|
||||
title: "Oops",
|
||||
});
|
||||
} else {
|
||||
toast({
|
||||
description: `User ${user} removed`,
|
||||
status: "success",
|
||||
title: "Success",
|
||||
});
|
||||
|
||||
setMods(mods.filter((mod: any) => mod.user !== user));
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<Modal isCentered isOpen={props.isOpen} onClose={props.onClose}>
|
||||
<ModalOverlay />
|
||||
<ModalContent>
|
||||
<ModalHeader>Game Moderators</ModalHeader>
|
||||
<ModalCloseButton />
|
||||
<ModalBody>
|
||||
<TableContainer>
|
||||
<Table variant="simple">
|
||||
<Thead>
|
||||
<Tr>
|
||||
<Th>User</Th>
|
||||
<Th>Added At</Th>
|
||||
<Th>Added By</Th>
|
||||
<Th>Remove</Th>
|
||||
</Tr>
|
||||
</Thead>
|
||||
<Tbody>
|
||||
{mods.map((mod: any) => (
|
||||
<Tr>
|
||||
<Td>{mod.user}</Td>
|
||||
<Td>{new Date(mod.metadata.time).toLocaleString()}</Td>
|
||||
<Td>{mod.metadata.user}</Td>
|
||||
<Td>
|
||||
<Link onClick={async () => await removeUser(mod.user)}>
|
||||
Remove
|
||||
</Link>
|
||||
</Td>
|
||||
</Tr>
|
||||
))}
|
||||
</Tbody>
|
||||
</Table>
|
||||
</TableContainer>
|
||||
<HStack mt="8px">
|
||||
<Input
|
||||
maxLength={19}
|
||||
onChange={(e) => setUserToAdd(e.target.value)}
|
||||
placeholder="1234567890987654321"
|
||||
/>
|
||||
<Button onClick={async () => await addUser()}>Add</Button>
|
||||
</HStack>
|
||||
</ModalBody>
|
||||
</ModalContent>
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
@@ -213,8 +213,8 @@ export default function (props: {
|
||||
</Link>
|
||||
<a href="/me">
|
||||
<Avatar
|
||||
display={data.id ? "" : "none"}
|
||||
height="64px"
|
||||
display={data.id ? "block" : "none"}
|
||||
height="32px"
|
||||
src={getAvatarUrl(data)}
|
||||
width="32px"
|
||||
/>
|
||||
|
||||
@@ -63,13 +63,20 @@ export default function (props: ReportCardProps & { port?: MessagePort }) {
|
||||
<Heading size="lg">
|
||||
Report for {props.target_usernames.toString()}
|
||||
</Heading>
|
||||
<Text fontSize="xs">ID(s): {props.target_ids.toString()}</Text>
|
||||
<VStack alignItems="start" gap={0} paddingTop="8px">
|
||||
<Text fontSize="xs">ID(s): {props.target_ids.toString()}</Text>
|
||||
<Text fontSize="xs">Report Type: {props.type}</Text>
|
||||
</VStack>
|
||||
</CardHeader>
|
||||
<CardBody>
|
||||
<div style={{ position: "relative" }}>
|
||||
<video controls={true} width="100%">
|
||||
<source src={`/api/uploads/${props.attachments[attachmentIdx]}`} />
|
||||
<source src="/files/processing.webm" />
|
||||
<img
|
||||
alt="User submission evidence"
|
||||
src={`/api/uploads/${props.attachments[attachmentIdx]}`}
|
||||
width="100%"
|
||||
/>
|
||||
</video>
|
||||
<HStack
|
||||
pos="absolute"
|
||||
@@ -151,6 +158,9 @@ export default function (props: ReportCardProps & { port?: MessagePort }) {
|
||||
<Radio key={2} value="2">
|
||||
Ban
|
||||
</Radio>
|
||||
<Radio key={3} value="3">
|
||||
Disallow Server Configurator
|
||||
</Radio>
|
||||
</VStack>
|
||||
</RadioGroup>,
|
||||
);
|
||||
|
||||
@@ -54,11 +54,6 @@
|
||||
"tag": "3_Row",
|
||||
"position": "Head of Wall Moderation"
|
||||
},
|
||||
{
|
||||
"id": "688414240209633441",
|
||||
"tag": "9t_d",
|
||||
"position": "Events Coordinator"
|
||||
},
|
||||
{
|
||||
"id": "884831305831948338",
|
||||
"tag": "Mustang",
|
||||
|
||||
@@ -271,7 +271,7 @@ async function setAuth(context: RequestContext) {
|
||||
|
||||
async function setBody(context: RequestContext) {
|
||||
if (
|
||||
context.request.method === "POST" &&
|
||||
["PATCH", "POST", "PUT"].includes(context.request.method) &&
|
||||
!context.request.url.endsWith("/api/infractions/new")
|
||||
) {
|
||||
if (
|
||||
|
||||
@@ -43,7 +43,6 @@ export async function onRequestPost(context: RequestContext) {
|
||||
.bind(context.params.id)
|
||||
.run();
|
||||
|
||||
|
||||
await fetch(
|
||||
`https://discord.com/api/v10/guilds/242263977986359297/bans/${appeal.user.id}`,
|
||||
{
|
||||
@@ -60,7 +59,7 @@ export async function onRequestPost(context: RequestContext) {
|
||||
embeds: [
|
||||
{
|
||||
title: "Appeal Accepted",
|
||||
color: 0x00ff00,
|
||||
color: 65280,
|
||||
description: `Appeal from user ${appeal.user.username} (${appeal.user.id}) was accepted.`,
|
||||
fields: [
|
||||
{
|
||||
|
||||
@@ -49,7 +49,7 @@ export async function onRequestPost(context: RequestContext) {
|
||||
embeds: [
|
||||
{
|
||||
title: "Appeal Denied",
|
||||
color: 0xff0000,
|
||||
color: 16711680,
|
||||
description: `Appeal from user ${appeal.user.username} (${appeal.user.id}) was denied.`,
|
||||
fields: [
|
||||
{
|
||||
|
||||
@@ -2,7 +2,7 @@ import { jsonResponse } from "../../common.js";
|
||||
|
||||
export async function onRequestGet(context: RequestContext) {
|
||||
const { results } = await context.env.D1.prepare(
|
||||
"SELECT * FROM appeal_bans;",
|
||||
"SELECT * FROM appeal_bans ORDER BY created_by DESC;",
|
||||
).all();
|
||||
|
||||
return jsonResponse(JSON.stringify(results));
|
||||
|
||||
@@ -74,6 +74,9 @@ export async function onRequestPatch(context: RequestContext) {
|
||||
const date = new Date();
|
||||
const currentDay = date.getUTCDate();
|
||||
|
||||
// Set to first of month to avoid any issues with month incrementation, then add month and subtract one day to get the last day of this month
|
||||
date.setUTCDate(1);
|
||||
date.setUTCMonth(date.getUTCMonth() + 1);
|
||||
date.setUTCDate(0);
|
||||
|
||||
if (
|
||||
@@ -88,7 +91,7 @@ export async function onRequestPatch(context: RequestContext) {
|
||||
|
||||
if (
|
||||
date.getUTCFullYear() !== eventData.year ||
|
||||
date.getUTCMonth() !== eventData.month
|
||||
date.getUTCMonth() + 1 !== eventData.month
|
||||
)
|
||||
return jsonError(
|
||||
"Only events in the current month period can be rescheduled",
|
||||
|
||||
@@ -14,22 +14,25 @@ export async function onRequestPost(context: RequestContext) {
|
||||
|
||||
if (!updatedEvent) return jsonError("This event does not exist", 404);
|
||||
|
||||
const email = await context.env.DATA.get(
|
||||
`eventemail_${context.data.event.id}`,
|
||||
);
|
||||
const emailData: { email: string; type: string } | null =
|
||||
await context.env.DATA.get(`eventemail_${context.data.event.id}`, {
|
||||
type: "json",
|
||||
});
|
||||
|
||||
const usernameData: Record<string, string> | null =
|
||||
await context.env.D1.prepare("SELECT name FROM et_members WHERE id = ?;")
|
||||
.bind(updatedEvent.created_by)
|
||||
.first();
|
||||
|
||||
if (email && usernameData) {
|
||||
if (emailData && usernameData) {
|
||||
await sendEmail(
|
||||
email,
|
||||
emailData.email,
|
||||
context.env.MAILGUN_API_KEY,
|
||||
`Event ${context.data.body.approved ? "Approved" : "Rejected"}`,
|
||||
`event_${context.data.body.approved ? "approved" : "rejected"}`,
|
||||
{
|
||||
date: `${updatedEvent.year}-${updatedEvent.month.toString().padStart(2, "0")}-${updatedEvent.day.toString().padStart(2, "0")}`,
|
||||
event: emailData.type,
|
||||
username: usernameData.name,
|
||||
},
|
||||
);
|
||||
|
||||
@@ -98,7 +98,7 @@ export async function onRequestPost(context: RequestContext) {
|
||||
if (type !== "gamenight")
|
||||
await context.env.DATA.put(
|
||||
`eventemail_${id}`,
|
||||
context.data.current_user.email,
|
||||
JSON.stringify({ email: context.data.current_user.email, type }),
|
||||
{ expirationTtl: 2678400 },
|
||||
);
|
||||
|
||||
|
||||
@@ -16,29 +16,49 @@ export async function onRequestPost(context: RequestContext) {
|
||||
if (!appeal) return jsonError("Appeal not found", 400);
|
||||
|
||||
const banList = (await getBanList(context)) as {
|
||||
[k: string]: { BanType: number; Unbanned?: boolean; UnbanReduct?: number };
|
||||
[k: string]: {
|
||||
BanType: number;
|
||||
hidden_from_leaderboards?: boolean;
|
||||
serverconfigurator_blacklist?: boolean;
|
||||
Unbanned?: boolean;
|
||||
UnbanReduct?: number;
|
||||
};
|
||||
};
|
||||
|
||||
await context.env.D1.prepare("DELETE FROM game_appeals WHERE id = ?;")
|
||||
.bind(context.params.id)
|
||||
.run();
|
||||
|
||||
if (!banList[appeal.roblox_id])
|
||||
if (!banList[appeal.roblox_id]?.BanType)
|
||||
return new Response(null, {
|
||||
status: 204,
|
||||
});
|
||||
|
||||
banList[appeal.roblox_id] = {
|
||||
BanType: 0,
|
||||
Unbanned: true,
|
||||
UnbanReduct: statsReduction,
|
||||
};
|
||||
if (banList[appeal.roblox_id].BanType === 2) {
|
||||
banList[appeal.roblox_id] = {
|
||||
BanType: 0,
|
||||
Unbanned: true,
|
||||
UnbanReduct: statsReduction,
|
||||
};
|
||||
} else if (appeal.type === "server configurator") {
|
||||
banList[appeal.roblox_id] = {
|
||||
...banList[appeal.roblox_id],
|
||||
serverconfigurator_blacklist: false,
|
||||
};
|
||||
} else if (appeal.type === "blacklist") {
|
||||
banList[appeal.roblox_id] = {
|
||||
...banList[appeal.roblox_id],
|
||||
hidden_from_leaderboards: false,
|
||||
Unbanned: true,
|
||||
UnbanReduct: statsReduction,
|
||||
};
|
||||
}
|
||||
|
||||
await context.env.D1.prepare(
|
||||
"INSERT INTO game_mod_logs (action, evidence, executed_at, executor, id, target) VALUES (?, ?, ?, ?, ?, ?);",
|
||||
)
|
||||
.bind(
|
||||
"accept_appeal",
|
||||
`accept appeal | ${banList[appeal.roblox_id]?.BanType === 2 ? "ban" : appeal.type}`,
|
||||
`https://carcrushers.cc/mod-queue?id=${context.params.id}&type=gma`,
|
||||
Date.now(),
|
||||
context.data.current_user.id,
|
||||
|
||||
@@ -3,8 +3,7 @@ import precheck from "./precheck.js";
|
||||
|
||||
export async function onRequestPost(context: RequestContext) {
|
||||
if (
|
||||
context.request.headers.get("rbx-auth") !==
|
||||
context.env.ROBLOX_APPEALS_TOKEN
|
||||
context.request.headers.get("rbx-auth") !== context.env.ROBLOX_APPEALS_TOKEN
|
||||
)
|
||||
return jsonError("Unauthorized", 401);
|
||||
|
||||
@@ -16,7 +15,7 @@ export async function onRequestPost(context: RequestContext) {
|
||||
|
||||
if (precheckData.error) return jsonError(precheckData.error, 500);
|
||||
|
||||
const { can_appeal, reason } = precheckData;
|
||||
const { can_appeal, reason, types } = precheckData;
|
||||
|
||||
return jsonResponse(JSON.stringify({ can_appeal, reason }));
|
||||
return jsonResponse(JSON.stringify({ can_appeal, reason, types }));
|
||||
}
|
||||
|
||||
@@ -3,9 +3,16 @@ import { getBanList } from "../../roblox-open-cloud.js";
|
||||
export default async function (
|
||||
context: RequestContext,
|
||||
user: number,
|
||||
): Promise<{ can_appeal?: boolean; error?: string; reason?: string }> {
|
||||
): Promise<{
|
||||
can_appeal?: boolean;
|
||||
error?: string;
|
||||
reason?: string;
|
||||
types?: string[];
|
||||
}> {
|
||||
if (
|
||||
await context.env.D1.prepare("SELECT * FROM game_appeals WHERE roblox_id = ?;")
|
||||
await context.env.D1.prepare(
|
||||
"SELECT * FROM game_appeals WHERE roblox_id = ?;",
|
||||
)
|
||||
.bind(user)
|
||||
.first()
|
||||
)
|
||||
@@ -18,7 +25,11 @@ export default async function (
|
||||
|
||||
try {
|
||||
banList = (await getBanList(context)) as {
|
||||
[k: number]: { BanType: number };
|
||||
[k: number]: {
|
||||
BanType: number;
|
||||
hidden_from_leaderboards?: boolean;
|
||||
serverconfigurator_blacklist?: boolean;
|
||||
};
|
||||
};
|
||||
} catch {
|
||||
return {
|
||||
@@ -42,24 +53,20 @@ export default async function (
|
||||
).toLocaleString()} to submit another appeal`,
|
||||
};
|
||||
|
||||
let userLogs;
|
||||
const userLogs = await context.env.D1.prepare(
|
||||
"SELECT executed_at FROM game_mod_logs WHERE target = ? ORDER BY executed_at DESC;",
|
||||
)
|
||||
.bind(user)
|
||||
.all();
|
||||
|
||||
try {
|
||||
userLogs = await context.env.D1.prepare(
|
||||
"SELECT executed_at FROM game_mod_logs WHERE target = ? ORDER BY executed_at DESC;",
|
||||
)
|
||||
.bind(user)
|
||||
.all();
|
||||
|
||||
if (userLogs.error) throw new Error("Query failed");
|
||||
} catch {
|
||||
if (userLogs.error)
|
||||
return {
|
||||
error: "Could not determine your eligibility",
|
||||
};
|
||||
}
|
||||
|
||||
// Legacy bans
|
||||
if (!userLogs.results.length) return { can_appeal: true, reason: "" };
|
||||
if (!userLogs.results.length)
|
||||
return { can_appeal: true, reason: "", types: ["ban"] };
|
||||
|
||||
const allowedTime = (userLogs.results[0].executed_at as number) + 2592000000;
|
||||
|
||||
@@ -71,5 +78,12 @@ export default async function (
|
||||
).toLocaleString()} to submit an appeal`,
|
||||
};
|
||||
|
||||
return { can_appeal: true, reason: "" };
|
||||
const types: string[] = [];
|
||||
|
||||
if (banList[user].BanType) types.push("ban");
|
||||
if (banList[user].hidden_from_leaderboards) types.push("leaderboard");
|
||||
if (banList[user].serverconfigurator_blacklist)
|
||||
types.push("server_configurator");
|
||||
|
||||
return { can_appeal: true, reason: "", types };
|
||||
}
|
||||
|
||||
@@ -7,11 +7,13 @@ export async function onRequestPost(context: RequestContext) {
|
||||
if (authHeader !== context.env.ROBLOX_APPEALS_TOKEN)
|
||||
return jsonError("Unauthorized", 401);
|
||||
|
||||
const { id, reasonForUnban, username, whatHappened } = context.data.body;
|
||||
const { id, reasonForUnban, type, username, whatHappened } =
|
||||
context.data.body;
|
||||
|
||||
if (
|
||||
typeof id !== "number" ||
|
||||
typeof reasonForUnban !== "string" ||
|
||||
!["ban", "leaderboard", "server_configurator"].includes(type) ||
|
||||
typeof username !== "string" ||
|
||||
typeof whatHappened !== "string"
|
||||
)
|
||||
@@ -43,14 +45,25 @@ export async function onRequestPost(context: RequestContext) {
|
||||
if (!precheckData.can_appeal)
|
||||
return jsonError(precheckData.reason as string, 400);
|
||||
|
||||
if (!precheckData.types?.includes(type))
|
||||
return jsonError("Specified punishment type is not applicable", 400);
|
||||
|
||||
const appealId = `${id}${
|
||||
context.request.headers.get("cf-ray")?.split("-")[0]
|
||||
}${Date.now()}`;
|
||||
|
||||
await context.env.D1.prepare(
|
||||
"INSERT INTO game_appeals (created_at, id, reason_for_unban, roblox_id, roblox_username, what_happened) VALUES (?, ?, ?, ?, ?, ?);",
|
||||
"INSERT INTO game_appeals (created_at, id, reason_for_unban, roblox_id, roblox_username, type, what_happened) VALUES (?, ?, ?, ?, ?, ?, ?);",
|
||||
)
|
||||
.bind(Date.now(), appealId, reasonForUnban, id, username, whatHappened)
|
||||
.bind(
|
||||
Date.now(),
|
||||
appealId,
|
||||
reasonForUnban,
|
||||
id,
|
||||
username,
|
||||
type,
|
||||
whatHappened,
|
||||
)
|
||||
.run();
|
||||
|
||||
await fetch(context.env.REPORTS_WEBHOOK, {
|
||||
|
||||
@@ -34,7 +34,11 @@ export async function onRequestGet(context: RequestContext) {
|
||||
|
||||
try {
|
||||
banList = (await getBanList(context)) as {
|
||||
[k: number]: { BanType: number };
|
||||
[k: number]: {
|
||||
BanType: number;
|
||||
hidden_from_leaderboards?: boolean;
|
||||
serverconfigurator_blacklist?: boolean;
|
||||
};
|
||||
};
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
@@ -47,8 +51,17 @@ export async function onRequestGet(context: RequestContext) {
|
||||
const banData = banList[users[0].id];
|
||||
|
||||
if (!banData?.BanType) current_status = "Not Moderated";
|
||||
else if (banData.BanType === 1) current_status = "Hidden from Leaderboards";
|
||||
else if (banData.BanType === 2) current_status = "Banned";
|
||||
else if (banData.BanType === 1) {
|
||||
if (
|
||||
banData.hidden_from_leaderboards &&
|
||||
banData.serverconfigurator_blacklist
|
||||
)
|
||||
current_status = "Hidden / Server Config Blocked";
|
||||
else if (banData.hidden_from_leaderboards)
|
||||
current_status = "Hidden From Leaderboards";
|
||||
else if (banData.serverconfigurator_blacklist)
|
||||
current_status = "Server Config Blocked";
|
||||
} else if (banData.BanType === 2) current_status = "Banned";
|
||||
|
||||
const response = {
|
||||
history: (
|
||||
|
||||
39
functions/api/game-bans/notes/[id].ts
Normal file
39
functions/api/game-bans/notes/[id].ts
Normal file
@@ -0,0 +1,39 @@
|
||||
import { jsonError, jsonResponse } from "../../../common.js";
|
||||
|
||||
export async function onRequestDelete(context: RequestContext) {
|
||||
const noteId = context.params.id as string;
|
||||
const creatorIdResult: null | Record<string, string> =
|
||||
await context.env.D1.prepare(
|
||||
"SELECT created_by FROM game_mod_logs WHERE id = ?;",
|
||||
)
|
||||
.bind(noteId)
|
||||
.first();
|
||||
|
||||
if (creatorIdResult?.created_by !== context.data.current_user.id)
|
||||
return jsonError("Cannot delete notes that are not your own", 403);
|
||||
|
||||
await context.env.D1.prepare("DELETE FROM game_mod_logs WHERE id = ?;")
|
||||
.bind(noteId)
|
||||
.first();
|
||||
|
||||
return new Response(null, { status: 204 });
|
||||
}
|
||||
|
||||
export async function onRequestGet(context: RequestContext) {
|
||||
const noteId = context.params.id as string;
|
||||
const result = await context.env.D1.prepare(
|
||||
"SELECT * FROM game_mod_notes WHERE id = ?;",
|
||||
)
|
||||
.bind(noteId)
|
||||
.first();
|
||||
|
||||
if (!result) return jsonError("Note not found", 404);
|
||||
|
||||
const noteData = structuredClone(result);
|
||||
const gmeEntry: null | { time: number; user: string; name: string } =
|
||||
await context.env.DATA.get(`gamemod_${result.created_by}`, "json");
|
||||
|
||||
if (gmeEntry) noteData.creator_name = gmeEntry.name;
|
||||
|
||||
return jsonResponse(JSON.stringify(noteData));
|
||||
}
|
||||
8
functions/api/game-bans/notes/_middleware.ts
Normal file
8
functions/api/game-bans/notes/_middleware.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
import { jsonError } from "../../../common.js";
|
||||
|
||||
export async function onRequest(context: RequestContext) {
|
||||
if (!(context.data.current_user?.permissions & (1 << 5)))
|
||||
return jsonError("Forbidden", 403);
|
||||
|
||||
return await context.next();
|
||||
}
|
||||
23
functions/api/game-bans/notes/create.ts
Normal file
23
functions/api/game-bans/notes/create.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
import { jsonError } from "../../../common.js";
|
||||
|
||||
export async function onRequestPost(context: RequestContext) {
|
||||
const { content, target } = context.data.body;
|
||||
|
||||
if (typeof content !== "string")
|
||||
return jsonError("'content' property is not a string", 400);
|
||||
|
||||
if (typeof target !== "number" || !Number.isSafeInteger(target))
|
||||
return jsonError("'target' property is not a valid number", 400);
|
||||
|
||||
if (content.length > 1000)
|
||||
return jsonError(
|
||||
"'content' property must be less than 1000 characters",
|
||||
400,
|
||||
);
|
||||
|
||||
const id = `${Date.now()}${crypto.randomUUID().replaceAll("-", "")}`;
|
||||
|
||||
await context.env.D1.prepare(
|
||||
"INSERT INTO game_mod_notes (content, created_at, created_by, id, target) VALUES (?, ?, ?, ?, ?);",
|
||||
).bind(content, Date.now(), context.data.current_user.id, id, target).first();
|
||||
}
|
||||
@@ -1,10 +1,13 @@
|
||||
import { jsonError } from "../../common.js";
|
||||
|
||||
export async function onRequestPost(context: RequestContext) {
|
||||
const { user } = context.data.body;
|
||||
const { user, name } = context.data.body;
|
||||
|
||||
if (!user) return jsonError("No user provided", 400);
|
||||
|
||||
if (typeof name !== "string" || name.length > 32)
|
||||
return jsonError("Invalid name", 400);
|
||||
|
||||
const existingUser = await context.env.DATA.get(`gamemod_${user}`);
|
||||
|
||||
if (existingUser) return jsonError("Cannot add an existing user", 400);
|
||||
@@ -20,7 +23,12 @@ export async function onRequestPost(context: RequestContext) {
|
||||
|
||||
if (!user.match(/^\d{17,19}$/)) return jsonError("Invalid User ID", 400);
|
||||
|
||||
const data = { time: Date.now(), user: context.data.current_user.id };
|
||||
const data = {
|
||||
created_at: Date.now(),
|
||||
created_by: context.data.current_user.id,
|
||||
id: user,
|
||||
name,
|
||||
};
|
||||
|
||||
await context.env.DATA.put(`gamemod_${user}`, JSON.stringify(data), {
|
||||
metadata: data,
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
import { jsonResponse } from "../../common.js";
|
||||
|
||||
export async function onRequestGet(context: RequestContext) {
|
||||
const list = await context.env.DATA.list({ prefix: "gamemod_" });
|
||||
const entries = [];
|
||||
|
||||
for (const key of list.keys)
|
||||
entries.push({
|
||||
metadata: key.metadata,
|
||||
user: key.name.replace("gamemod_", ""),
|
||||
});
|
||||
|
||||
return jsonResponse(JSON.stringify(entries));
|
||||
}
|
||||
@@ -91,8 +91,10 @@ export async function onRequestPost(context: RequestContext) {
|
||||
requestedNotice.decisions,
|
||||
);
|
||||
|
||||
for (const department of userAdminDepartments)
|
||||
for (const department of userAdminDepartments) {
|
||||
if (!JSON.parse(requestedNotice.departments).includes(department)) continue;
|
||||
decisions[department] = accepted;
|
||||
}
|
||||
|
||||
const applicableDepartments = JSON.parse(requestedNotice.departments).length;
|
||||
|
||||
|
||||
@@ -25,6 +25,11 @@ export async function onRequestGet(context: RequestContext) {
|
||||
if (!data || data.user?.id !== context.data.current_user.id)
|
||||
return jsonError("Item does not exist", 404);
|
||||
|
||||
if (type === "inactivity") {
|
||||
data.decisions = JSON.parse(data.decisions);
|
||||
data.departments = JSON.parse(data.departments);
|
||||
}
|
||||
|
||||
if (type === "report") {
|
||||
data.attachments = JSON.parse(data.attachments);
|
||||
data.target_ids = JSON.parse(data.target_ids);
|
||||
|
||||
@@ -5,7 +5,7 @@ export async function onRequestGet(context: RequestContext) {
|
||||
[k: string]: { permissions: number[]; table: string };
|
||||
} = {
|
||||
appeal: {
|
||||
permissions: [1 << 0, 1 << 1],
|
||||
permissions: [1 << 0, 1 << 11],
|
||||
table: "appeals",
|
||||
},
|
||||
gma: {
|
||||
|
||||
@@ -12,7 +12,7 @@ export async function onRequestGet(context: RequestContext): Promise<any> {
|
||||
report: "reports",
|
||||
};
|
||||
const permissions: { [k: string]: number[] } = {
|
||||
appeal: [1 << 0, 1 << 1],
|
||||
appeal: [1 << 0, 1 << 11],
|
||||
gma: [1 << 5],
|
||||
inactivity: [1 << 4, 1 << 6, 1 << 7, 1 << 11, 1 << 12],
|
||||
report: [1 << 5],
|
||||
|
||||
@@ -14,22 +14,30 @@ export async function onRequestPost(context: RequestContext) {
|
||||
if (!report) return jsonError("Report does not exist", 404);
|
||||
|
||||
const actionMap = context.data.body;
|
||||
const newActions: { [k: string]: { BanType: number } } = {};
|
||||
const newActions: {
|
||||
[k: string]: {
|
||||
BanType: number;
|
||||
hidden_from_leaderboards?: boolean;
|
||||
serverconfigurator_blacklist?: boolean;
|
||||
};
|
||||
} = {};
|
||||
const logMap: { [k: string]: number } = {};
|
||||
const user = JSON.parse(report.user);
|
||||
|
||||
for (const [user, action] of Object.entries(actionMap)) {
|
||||
for (let [user, action] of Object.entries(actionMap)) {
|
||||
if (
|
||||
isNaN(parseInt(user)) ||
|
||||
typeof action !== "number" ||
|
||||
action < 0 ||
|
||||
action > 2
|
||||
action > 3
|
||||
)
|
||||
return jsonError("Invalid action map", 400);
|
||||
|
||||
if (action === 0) continue;
|
||||
|
||||
newActions[user] = { BanType: action };
|
||||
newActions[user] = {
|
||||
BanType: action,
|
||||
};
|
||||
logMap[user] = action;
|
||||
}
|
||||
|
||||
@@ -41,9 +49,11 @@ export async function onRequestPost(context: RequestContext) {
|
||||
const actionMap: { [k: number]: string } = {
|
||||
1: "blacklist",
|
||||
2: "ban",
|
||||
3: "server config block",
|
||||
};
|
||||
|
||||
for (const [k, v] of Object.entries(logMap)) {
|
||||
// If ignore action
|
||||
if (v === 0) continue;
|
||||
|
||||
batchedQueries.push(
|
||||
@@ -56,12 +66,24 @@ export async function onRequestPost(context: RequestContext) {
|
||||
parseInt(k),
|
||||
),
|
||||
);
|
||||
|
||||
// If not a ban action
|
||||
if (v === 1) {
|
||||
newActions[k].hidden_from_leaderboards = true;
|
||||
} else if (v === 3) {
|
||||
newActions[k].serverconfigurator_blacklist = true;
|
||||
newActions[k].BanType = 1;
|
||||
}
|
||||
}
|
||||
|
||||
await context.env.D1.batch(batchedQueries);
|
||||
|
||||
const banList = (await getBanList(context)) as {
|
||||
[k: string]: { BanType: number };
|
||||
[k: string]: {
|
||||
BanType: number;
|
||||
hidden_from_leaderboards?: boolean;
|
||||
serverconfigurator_blacklist?: boolean;
|
||||
};
|
||||
};
|
||||
|
||||
await setBanList(context, Object.assign(banList, newActions));
|
||||
|
||||
@@ -2,8 +2,14 @@ import { jsonError, jsonResponse } from "../../common.js";
|
||||
import upload from "../../upload.js";
|
||||
|
||||
export async function onRequestPost(context: RequestContext) {
|
||||
const { description, files, senderTokenId, turnstileResponse, usernames } =
|
||||
context.data.body;
|
||||
const {
|
||||
description,
|
||||
files,
|
||||
senderTokenId,
|
||||
submissionType,
|
||||
turnstileResponse,
|
||||
usernames,
|
||||
} = context.data.body;
|
||||
|
||||
if (!context.data.current_user) {
|
||||
if (typeof turnstileResponse !== "string")
|
||||
@@ -32,6 +38,9 @@ export async function onRequestPost(context: RequestContext) {
|
||||
if (!Array.isArray(usernames))
|
||||
return jsonError("Usernames must be type of array", 400);
|
||||
|
||||
if (!["abuse", "exploit"].includes(submissionType))
|
||||
return jsonError("Invalid submission type", 400);
|
||||
|
||||
if (
|
||||
!["string", "undefined"].includes(typeof description) ||
|
||||
description?.length > 512
|
||||
@@ -131,7 +140,19 @@ export async function onRequestPost(context: RequestContext) {
|
||||
|
||||
if (
|
||||
fileParts.length < 2 ||
|
||||
!["mkv", "mp4", "wmv", "m4v", "gif", "webm"].includes(fileExten)
|
||||
![
|
||||
"avif",
|
||||
"gif",
|
||||
"jpeg",
|
||||
"jpg",
|
||||
"m4v",
|
||||
"mkv",
|
||||
"mp4",
|
||||
"png",
|
||||
"webm",
|
||||
"webp",
|
||||
"wmv",
|
||||
].includes(fileExten)
|
||||
)
|
||||
return jsonError(
|
||||
`File ${file.name} cannot be uploaded as it is unsupported`,
|
||||
@@ -162,9 +183,10 @@ export async function onRequestPost(context: RequestContext) {
|
||||
|
||||
const uploadUrlResults = await Promise.allSettled(uploadUrlPromises);
|
||||
|
||||
const reportId = `${Date.now()}${context.request.headers.get(
|
||||
"cf-ray",
|
||||
)}${crypto.randomUUID().replaceAll("-", "")}`;
|
||||
const reportId = `${Date.now()}${context.request.headers
|
||||
.get("cf-ray")
|
||||
?.split("-")
|
||||
?.at(0)}${crypto.randomUUID().replaceAll("-", "")}`;
|
||||
|
||||
const { current_user: currentUser } = context.data;
|
||||
if (filesToProcess.length)
|
||||
@@ -196,7 +218,7 @@ export async function onRequestPost(context: RequestContext) {
|
||||
}
|
||||
|
||||
await context.env.D1.prepare(
|
||||
"INSERT INTO reports (attachments, created_at, id, open, target_ids, target_usernames, user) VALUES (?, ?, ?, 1, ?, ?, ?);",
|
||||
"INSERT INTO reports (attachments, created_at, id, open, target_ids, target_usernames, type, user) VALUES (?, ?, ?, 1, ?, ?, ?, ?);",
|
||||
)
|
||||
.bind(
|
||||
JSON.stringify(attachments),
|
||||
@@ -204,6 +226,7 @@ export async function onRequestPost(context: RequestContext) {
|
||||
reportId,
|
||||
JSON.stringify(metaIDs),
|
||||
JSON.stringify(metaNames),
|
||||
submissionType,
|
||||
currentUser ? JSON.stringify(currentUser) : null,
|
||||
)
|
||||
.run();
|
||||
|
||||
@@ -1,12 +1,17 @@
|
||||
import { AwsClient } from "aws4fetch";
|
||||
|
||||
const contentTypes: { [k: string]: string } = {
|
||||
avif: "image/avif",
|
||||
gif: "image/gif",
|
||||
jpeg: "image/jpeg",
|
||||
jpg: "image/jpeg",
|
||||
m4v: "video/x-m4v",
|
||||
mkv: "video/x-matroska",
|
||||
mov: "video/mp4",
|
||||
mp4: "video/mp4",
|
||||
png: "image/png",
|
||||
webm: "video/webm",
|
||||
webp: "image/webp",
|
||||
wmv: "video/x-ms-wmv",
|
||||
};
|
||||
|
||||
|
||||
4
index.d.ts
vendored
4
index.d.ts
vendored
@@ -15,7 +15,7 @@ declare global {
|
||||
event_id: string;
|
||||
event_type: string;
|
||||
token: string;
|
||||
}
|
||||
};
|
||||
|
||||
type RequestContext = EventContext<Env, string, { [k: string]: any }>;
|
||||
|
||||
@@ -39,6 +39,7 @@ declare global {
|
||||
reason_for_unban: string;
|
||||
roblox_id: number;
|
||||
roblox_username: string;
|
||||
type: string;
|
||||
what_happened: string;
|
||||
}
|
||||
|
||||
@@ -71,6 +72,7 @@ declare global {
|
||||
open: boolean;
|
||||
target_ids: number[];
|
||||
target_usernames: string[];
|
||||
type: string;
|
||||
user?: {
|
||||
id: string;
|
||||
username: string;
|
||||
|
||||
443
package-lock.json
generated
443
package-lock.json
generated
@@ -8,30 +8,30 @@
|
||||
"name": "car-crushers-portal",
|
||||
"version": "0.0.0",
|
||||
"dependencies": {
|
||||
"@chakra-ui/react": "^2.10.6",
|
||||
"@chakra-ui/react": "^2.10.9",
|
||||
"@emotion/react": "^11.14.0",
|
||||
"@emotion/styled": "^11.14.0",
|
||||
"@fontsource-variable/plus-jakarta-sans": "^5.2.5",
|
||||
"@remix-run/cloudflare": "^2.16.0",
|
||||
"@remix-run/cloudflare-pages": "^2.16.0",
|
||||
"@remix-run/react": "^2.16.0",
|
||||
"@sentry/react": "^9.5.0",
|
||||
"@emotion/styled": "^11.14.1",
|
||||
"@fontsource-variable/plus-jakarta-sans": "^5.2.8",
|
||||
"@remix-run/cloudflare": "^2.17.1",
|
||||
"@remix-run/cloudflare-pages": "^2.17.1",
|
||||
"@remix-run/react": "^2.17.1",
|
||||
"@sentry/react": "^10.21.0",
|
||||
"aws4fetch": "^1.0.20",
|
||||
"dayjs": "^1.11.13",
|
||||
"framer-motion": "^12.5.0",
|
||||
"dayjs": "^1.11.18",
|
||||
"framer-motion": "^12.23.24",
|
||||
"react": "^18.3.1",
|
||||
"react-big-calendar": "^1.18.0",
|
||||
"react-big-calendar": "^1.19.4",
|
||||
"react-dom": "^18.3.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@remix-run/dev": "^2.16.0",
|
||||
"@types/node": "^22.13.10",
|
||||
"@types/react": "^18.3.18",
|
||||
"@types/react-big-calendar": "^1.16.1",
|
||||
"@types/react-dom": "^18.3.5",
|
||||
"dotenv": "^16.4.7",
|
||||
"prettier": "^3.5.3",
|
||||
"typescript": "^5.8.2"
|
||||
"@remix-run/dev": "^2.17.1",
|
||||
"@types/node": "^24.9.1",
|
||||
"@types/react": "^18.3.26",
|
||||
"@types/react-big-calendar": "^1.16.3",
|
||||
"@types/react-dom": "^18.3.7",
|
||||
"dotenv": "^17.2.3",
|
||||
"prettier": "^3.6.2",
|
||||
"typescript": "^5.9.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@ampproject/remapping": {
|
||||
@@ -549,12 +549,12 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@chakra-ui/hooks": {
|
||||
"version": "2.4.4",
|
||||
"resolved": "https://registry.npmjs.org/@chakra-ui/hooks/-/hooks-2.4.4.tgz",
|
||||
"integrity": "sha512-+gMwLIkabtddIL/GICU7JmnYtvfONP+fNiTfdYLV9/I1eyCz8igKgLmFJOGM6F+BpUev6hh+/+DX5ezGQ9VTbQ==",
|
||||
"version": "2.4.5",
|
||||
"resolved": "https://registry.npmjs.org/@chakra-ui/hooks/-/hooks-2.4.5.tgz",
|
||||
"integrity": "sha512-601fWfHE2i7UjaxK/9lDLlOni6vk/I+04YDbM0BrelJy+eqxdlOmoN8Z6MZ3PzFh7ofERUASor+vL+/HaCaZ7w==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@chakra-ui/utils": "2.2.4",
|
||||
"@chakra-ui/utils": "2.2.5",
|
||||
"@zag-js/element-size": "0.31.1",
|
||||
"copy-to-clipboard": "3.3.3",
|
||||
"framesync": "6.1.2"
|
||||
@@ -564,15 +564,15 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@chakra-ui/react": {
|
||||
"version": "2.10.6",
|
||||
"resolved": "https://registry.npmjs.org/@chakra-ui/react/-/react-2.10.6.tgz",
|
||||
"integrity": "sha512-9cdzcUR3LV3E2as0QhZhHAH5qjbyspV12kU1E1Ibcv6/uKUi6bIfPfMSC6R/Tw8Beqhn2ClJFPqjtXzL+C0knQ==",
|
||||
"version": "2.10.9",
|
||||
"resolved": "https://registry.npmjs.org/@chakra-ui/react/-/react-2.10.9.tgz",
|
||||
"integrity": "sha512-lhdcgoocOiURwBNR3L8OioCNIaGCZqRfuKioLyaQLjOanl4jr0PQclsGb+w0cmito252vEWpsz2xRqF7y+Flrw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@chakra-ui/hooks": "2.4.4",
|
||||
"@chakra-ui/styled-system": "2.12.2",
|
||||
"@chakra-ui/theme": "3.4.8",
|
||||
"@chakra-ui/utils": "2.2.4",
|
||||
"@chakra-ui/hooks": "2.4.5",
|
||||
"@chakra-ui/styled-system": "2.12.4",
|
||||
"@chakra-ui/theme": "3.4.9",
|
||||
"@chakra-ui/utils": "2.2.5",
|
||||
"@popperjs/core": "^2.11.8",
|
||||
"@zag-js/focus-visible": "^0.31.1",
|
||||
"aria-hidden": "^1.2.3",
|
||||
@@ -589,37 +589,37 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@chakra-ui/styled-system": {
|
||||
"version": "2.12.2",
|
||||
"resolved": "https://registry.npmjs.org/@chakra-ui/styled-system/-/styled-system-2.12.2.tgz",
|
||||
"integrity": "sha512-BlQ7i3+GYC0S0c72B+paa0sYo+QeNSMfz6fwQRFsc8A5Aax9i9lSdRL+vwJVC+k6r/0HWfRwk016R2RD2ihEwQ==",
|
||||
"version": "2.12.4",
|
||||
"resolved": "https://registry.npmjs.org/@chakra-ui/styled-system/-/styled-system-2.12.4.tgz",
|
||||
"integrity": "sha512-oa07UG7Lic5hHSQtGRiMEnYjuhIa8lszyuVhZjZqR2Ap3VMF688y1MVPJ1pK+8OwY5uhXBgVd5c0+rI8aBZlwg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@chakra-ui/utils": "2.2.4",
|
||||
"@chakra-ui/utils": "2.2.5",
|
||||
"csstype": "^3.1.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@chakra-ui/theme": {
|
||||
"version": "3.4.8",
|
||||
"resolved": "https://registry.npmjs.org/@chakra-ui/theme/-/theme-3.4.8.tgz",
|
||||
"integrity": "sha512-ZLMP2Gek38ZTIlj+sMZLsd1TW27yVdmUKMfBmjsr1psAeOa5bDBLKDszICjhEqk7gAbiWB7jr1/HzBXid4kduQ==",
|
||||
"version": "3.4.9",
|
||||
"resolved": "https://registry.npmjs.org/@chakra-ui/theme/-/theme-3.4.9.tgz",
|
||||
"integrity": "sha512-GAom2SjSdRWTcX76/2yJOFJsOWHQeBgaynCUNBsHq62OafzvELrsSHDUw0bBqBb1c2ww0CclIvGilPup8kXBFA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@chakra-ui/anatomy": "2.3.6",
|
||||
"@chakra-ui/theme-tools": "2.2.8",
|
||||
"@chakra-ui/utils": "2.2.4"
|
||||
"@chakra-ui/theme-tools": "2.2.9",
|
||||
"@chakra-ui/utils": "2.2.5"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@chakra-ui/styled-system": ">=2.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@chakra-ui/theme-tools": {
|
||||
"version": "2.2.8",
|
||||
"resolved": "https://registry.npmjs.org/@chakra-ui/theme-tools/-/theme-tools-2.2.8.tgz",
|
||||
"integrity": "sha512-X2i2qgkG+k3DQfh/adn3zzM4Ty8QrGobVPjMl9rMrEYq3ac+pur6KVdVHy/SwwoPvB6S4i84uq7y35+KbJan9g==",
|
||||
"version": "2.2.9",
|
||||
"resolved": "https://registry.npmjs.org/@chakra-ui/theme-tools/-/theme-tools-2.2.9.tgz",
|
||||
"integrity": "sha512-PcbYL19lrVvEc7Oydy//jsy/MO/rZz1DvLyO6AoI+bI/+Kwz9WfOKsspbulEhRg5COayE0R/IZPsskXZ7Mp4bA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@chakra-ui/anatomy": "2.3.6",
|
||||
"@chakra-ui/utils": "2.2.4",
|
||||
"@chakra-ui/utils": "2.2.5",
|
||||
"color2k": "^2.0.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
@@ -627,9 +627,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@chakra-ui/utils": {
|
||||
"version": "2.2.4",
|
||||
"resolved": "https://registry.npmjs.org/@chakra-ui/utils/-/utils-2.2.4.tgz",
|
||||
"integrity": "sha512-nRpR9SnX7aLcJx7lKu8kgQWxdJso1oR/78HcBI+mzidvWdTykbTGdm5Q2R7S0PVH1IFBzBTgi6TiAjHvu96auA==",
|
||||
"version": "2.2.5",
|
||||
"resolved": "https://registry.npmjs.org/@chakra-ui/utils/-/utils-2.2.5.tgz",
|
||||
"integrity": "sha512-KTBCK+M5KtXH6p54XS39ImQUMVtAx65BoZDoEms3LuObyTo1+civ1sMm4h3nRT320U6H5H7D35WnABVQjqU/4g==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/lodash.mergewith": "4.6.9",
|
||||
@@ -649,9 +649,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@cloudflare/workers-types": {
|
||||
"version": "4.20250311.0",
|
||||
"resolved": "https://registry.npmjs.org/@cloudflare/workers-types/-/workers-types-4.20250311.0.tgz",
|
||||
"integrity": "sha512-5ftSdP1vEdKM6in4p3DZ5SIgaJtRh6LqVeitQtFFsHCyHSPES0KX5HaqTYai+T/5UwmZrB2a3fBUKpGmfDOXBg==",
|
||||
"version": "4.20251014.0",
|
||||
"resolved": "https://registry.npmjs.org/@cloudflare/workers-types/-/workers-types-4.20251014.0.tgz",
|
||||
"integrity": "sha512-tEW98J/kOa0TdylIUOrLKRdwkUw0rvvYVlo+Ce0mqRH3c8kSoxLzUH9gfCvwLe0M89z1RkzFovSKAW2Nwtyn3w==",
|
||||
"license": "MIT OR Apache-2.0",
|
||||
"peer": true
|
||||
},
|
||||
@@ -752,9 +752,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@emotion/styled": {
|
||||
"version": "11.14.0",
|
||||
"resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-11.14.0.tgz",
|
||||
"integrity": "sha512-XxfOnXFffatap2IyCeJyNov3kiDQWoR08gPUQxvbL7fxKryGBKUZUkG6Hz48DZwVrJSVh9sJboyV1Ds4OW6SgA==",
|
||||
"version": "11.14.1",
|
||||
"resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-11.14.1.tgz",
|
||||
"integrity": "sha512-qEEJt42DuToa3gurlH4Qqc1kVpNq8wO8cJtDzU46TjlzWjDlsVyevtYCRijVq3SrHsROS+gVQ8Fnea108GnKzw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.18.3",
|
||||
@@ -1193,9 +1193,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@fontsource-variable/plus-jakarta-sans": {
|
||||
"version": "5.2.5",
|
||||
"resolved": "https://registry.npmjs.org/@fontsource-variable/plus-jakarta-sans/-/plus-jakarta-sans-5.2.5.tgz",
|
||||
"integrity": "sha512-nkAWzq+QWBSK+52HIlNCyoh5YXrZ/AwV1OqzxZz6VnPmsIpU68B1bf1YT8heRAJKY1kXNtWIJ9jJMYVaStgf+w==",
|
||||
"version": "5.2.8",
|
||||
"resolved": "https://registry.npmjs.org/@fontsource-variable/plus-jakarta-sans/-/plus-jakarta-sans-5.2.8.tgz",
|
||||
"integrity": "sha512-iQecBizIdZxezODNHzOn4SvvRMrZL/S8k4MEXGDynCmUrImVW0VmX+tIAMqnADwH4haXlHSXqMgU6+kcfBQJdw==",
|
||||
"license": "OFL-1.1",
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ayuhito"
|
||||
@@ -1401,13 +1401,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@remix-run/cloudflare": {
|
||||
"version": "2.16.0",
|
||||
"resolved": "https://registry.npmjs.org/@remix-run/cloudflare/-/cloudflare-2.16.0.tgz",
|
||||
"integrity": "sha512-Z9kN6tChe36S175z4AVm8c79kUUBS4k16IBIpNods3z3oyo103EDawHdpiYcaEdz2OfdTCvNwsA7zLvRBW7yNA==",
|
||||
"version": "2.17.1",
|
||||
"resolved": "https://registry.npmjs.org/@remix-run/cloudflare/-/cloudflare-2.17.1.tgz",
|
||||
"integrity": "sha512-JdtThzjMgLiC7Hdg9pO3dX2LRcNdV///fAB8OjAbICfVmR4pgXRffcQLBNH3OSvnk1nwLvseugozUmZTHwbg4Q==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@cloudflare/kv-asset-handler": "^0.1.3",
|
||||
"@remix-run/server-runtime": "2.16.0"
|
||||
"@remix-run/server-runtime": "2.17.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
@@ -1423,12 +1423,12 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@remix-run/cloudflare-pages": {
|
||||
"version": "2.16.0",
|
||||
"resolved": "https://registry.npmjs.org/@remix-run/cloudflare-pages/-/cloudflare-pages-2.16.0.tgz",
|
||||
"integrity": "sha512-Il/4JWkIFhkGPqE9MtaWCG431wNvAo+JsGClwVnOQgQYOJKV7wcvjZ4fQmkzc+GYBGMlOxx1OxD/S76XqnVzFQ==",
|
||||
"version": "2.17.1",
|
||||
"resolved": "https://registry.npmjs.org/@remix-run/cloudflare-pages/-/cloudflare-pages-2.17.1.tgz",
|
||||
"integrity": "sha512-ATJOyO+mu50NzPS74b/7fe6TTgMC+HM3yMd3M5SdqaLu+McPBaldnJrP+WAXNbPCJXDeoFbMneBpfnS1p2TAPQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@remix-run/cloudflare": "2.16.0"
|
||||
"@remix-run/cloudflare": "2.17.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
@@ -1444,9 +1444,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@remix-run/dev": {
|
||||
"version": "2.16.0",
|
||||
"resolved": "https://registry.npmjs.org/@remix-run/dev/-/dev-2.16.0.tgz",
|
||||
"integrity": "sha512-zfb93zJatWRMmBU4dQFM9pTgYfkZi1orDYtd18f9YNZM6pbshmhqlsiGZmrMAhAuYLGB983aqkXY3pxtZhoDkQ==",
|
||||
"version": "2.17.1",
|
||||
"resolved": "https://registry.npmjs.org/@remix-run/dev/-/dev-2.17.1.tgz",
|
||||
"integrity": "sha512-Ou9iIewCs4IIoC5FjYBsfNzcCfdrc+3V8thRjULVMvTDfFxRoL+uNz/AlD3jC7Vm8Q08Iryy0joCOh8oghIhvQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -1460,9 +1460,9 @@
|
||||
"@babel/types": "^7.22.5",
|
||||
"@mdx-js/mdx": "^2.3.0",
|
||||
"@npmcli/package-json": "^4.0.1",
|
||||
"@remix-run/node": "2.16.0",
|
||||
"@remix-run/node": "2.17.1",
|
||||
"@remix-run/router": "1.23.0",
|
||||
"@remix-run/server-runtime": "2.16.0",
|
||||
"@remix-run/server-runtime": "2.17.1",
|
||||
"@types/mdx": "^2.0.5",
|
||||
"@vanilla-extract/integration": "^6.2.0",
|
||||
"arg": "^5.0.1",
|
||||
@@ -1501,10 +1501,10 @@
|
||||
"remark-mdx-frontmatter": "^1.0.1",
|
||||
"semver": "^7.3.7",
|
||||
"set-cookie-parser": "^2.6.0",
|
||||
"tar-fs": "^2.1.1",
|
||||
"tar-fs": "^2.1.3",
|
||||
"tsconfig-paths": "^4.0.0",
|
||||
"valibot": "^0.41.0",
|
||||
"vite-node": "3.0.0-beta.2",
|
||||
"vite-node": "^3.1.3",
|
||||
"ws": "^7.5.10"
|
||||
},
|
||||
"bin": {
|
||||
@@ -1514,8 +1514,8 @@
|
||||
"node": ">=18.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@remix-run/react": "^2.16.0",
|
||||
"@remix-run/serve": "^2.16.0",
|
||||
"@remix-run/react": "^2.17.0",
|
||||
"@remix-run/serve": "^2.17.0",
|
||||
"typescript": "^5.1.0",
|
||||
"vite": "^5.1.0 || ^6.0.0",
|
||||
"wrangler": "^3.28.2"
|
||||
@@ -1588,6 +1588,19 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@remix-run/dev/node_modules/dotenv": {
|
||||
"version": "16.6.1",
|
||||
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz",
|
||||
"integrity": "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==",
|
||||
"dev": true,
|
||||
"license": "BSD-2-Clause",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://dotenvx.com"
|
||||
}
|
||||
},
|
||||
"node_modules/@remix-run/dev/node_modules/has-flag": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
|
||||
@@ -1628,17 +1641,17 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@remix-run/dev/node_modules/vite-node": {
|
||||
"version": "3.0.0-beta.2",
|
||||
"resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.0.0-beta.2.tgz",
|
||||
"integrity": "sha512-ofTf6cfRdL30Wbl9n/BX81EyIR5s4PReLmSurrxQ+koLaWUNOEo8E0lCM53OJkb8vpa2URM2nSrxZsIFyvY1rg==",
|
||||
"version": "3.2.3",
|
||||
"resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.2.3.tgz",
|
||||
"integrity": "sha512-gc8aAifGuDIpZHrPjuHyP4dpQmYXqWw7D1GmDnWeNWP654UEXzVfQ5IHPSK5HaHkwB/+p1atpYpSdw/2kOv8iQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"cac": "^6.7.14",
|
||||
"debug": "^4.4.0",
|
||||
"es-module-lexer": "^1.5.4",
|
||||
"pathe": "^1.1.2",
|
||||
"vite": "^5.0.0 || ^6.0.0"
|
||||
"debug": "^4.4.1",
|
||||
"es-module-lexer": "^1.7.0",
|
||||
"pathe": "^2.0.3",
|
||||
"vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0"
|
||||
},
|
||||
"bin": {
|
||||
"vite-node": "vite-node.mjs"
|
||||
@@ -1650,20 +1663,27 @@
|
||||
"url": "https://opencollective.com/vitest"
|
||||
}
|
||||
},
|
||||
"node_modules/@remix-run/dev/node_modules/vite-node/node_modules/pathe": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz",
|
||||
"integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@remix-run/node": {
|
||||
"version": "2.16.0",
|
||||
"resolved": "https://registry.npmjs.org/@remix-run/node/-/node-2.16.0.tgz",
|
||||
"integrity": "sha512-9yYBYCHYO1+bIScGAtOy5/r4BoTS8E5lpQmjWP99UxSCSiKHPEO76V9Z8mmmarTNis/FPN+sUwfmbQWNHLA2vw==",
|
||||
"version": "2.17.1",
|
||||
"resolved": "https://registry.npmjs.org/@remix-run/node/-/node-2.17.1.tgz",
|
||||
"integrity": "sha512-pHmHTuLE1Lwazulx3gjrHobgBCsa+Xiq8WUO0ruLeDfEw2DU0c0SNSiyNkugu3rIZautroBwRaOoy7CWJL9xhQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@remix-run/server-runtime": "2.16.0",
|
||||
"@remix-run/server-runtime": "2.17.1",
|
||||
"@remix-run/web-fetch": "^4.4.2",
|
||||
"@web3-storage/multipart-parser": "^1.0.0",
|
||||
"cookie-signature": "^1.1.0",
|
||||
"source-map-support": "^0.5.21",
|
||||
"stream-slice": "^0.1.2",
|
||||
"undici": "^6.11.1"
|
||||
"undici": "^6.21.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
@@ -1678,16 +1698,16 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@remix-run/react": {
|
||||
"version": "2.16.0",
|
||||
"resolved": "https://registry.npmjs.org/@remix-run/react/-/react-2.16.0.tgz",
|
||||
"integrity": "sha512-eTi60/7AO8vnIL+IT33ZixT0tLjUrilgKhimdZtddBc/XIawUeslC01mNUHIlLXS+zUDM05iBmY2aLTKkqyy6Q==",
|
||||
"version": "2.17.1",
|
||||
"resolved": "https://registry.npmjs.org/@remix-run/react/-/react-2.17.1.tgz",
|
||||
"integrity": "sha512-5MqRK2Z5gkQMDqGfjXSACf/HzvOA+5ug9kiSqaPpK9NX0OF4NlS+cAPKXQWuzc2iLSp6r1RGu8FU1jpZbhsaug==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@remix-run/router": "1.23.0",
|
||||
"@remix-run/server-runtime": "2.16.0",
|
||||
"@remix-run/server-runtime": "2.17.1",
|
||||
"react-router": "6.30.0",
|
||||
"react-router-dom": "6.30.0",
|
||||
"turbo-stream": "2.4.0"
|
||||
"turbo-stream": "2.4.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
@@ -1713,18 +1733,18 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@remix-run/server-runtime": {
|
||||
"version": "2.16.0",
|
||||
"resolved": "https://registry.npmjs.org/@remix-run/server-runtime/-/server-runtime-2.16.0.tgz",
|
||||
"integrity": "sha512-gbuc4slxPi+pT47MrUYprX/wCuDlYL6H3LHZSvimWO1kDCBt8oefHzdHDPjLi4B1xzqXZomswTbuJzpZ7xRRTg==",
|
||||
"version": "2.17.1",
|
||||
"resolved": "https://registry.npmjs.org/@remix-run/server-runtime/-/server-runtime-2.17.1.tgz",
|
||||
"integrity": "sha512-d1Vp9FxX4KafB111vP2E5C1fmWzPI+gHZ674L1drq+N8Bp9U6FBspi7GAZSU5K5Kxa4T6UF+aE1gK6pVi9R8sw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@remix-run/router": "1.23.0",
|
||||
"@types/cookie": "^0.6.0",
|
||||
"@web3-storage/multipart-parser": "^1.0.0",
|
||||
"cookie": "^0.6.0",
|
||||
"cookie": "^0.7.2",
|
||||
"set-cookie-parser": "^2.4.8",
|
||||
"source-map": "^0.7.3",
|
||||
"turbo-stream": "2.4.0"
|
||||
"turbo-stream": "2.4.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
@@ -1739,12 +1759,12 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@remix-run/server-runtime/node_modules/source-map": {
|
||||
"version": "0.7.4",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz",
|
||||
"integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==",
|
||||
"version": "0.7.6",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.6.tgz",
|
||||
"integrity": "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==",
|
||||
"license": "BSD-3-Clause",
|
||||
"engines": {
|
||||
"node": ">= 8"
|
||||
"node": ">= 12"
|
||||
}
|
||||
},
|
||||
"node_modules/@remix-run/web-blob": {
|
||||
@@ -2045,88 +2065,88 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@sentry-internal/browser-utils": {
|
||||
"version": "9.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry-internal/browser-utils/-/browser-utils-9.5.0.tgz",
|
||||
"integrity": "sha512-AE9jgeI5+KyGvLR0vf1I6sesi0NZXZe6pDlZNXyg+pWZB2vkE9dksE8ZsoU+YiD9zjUqazgPcVyb3O0VvmaCGw==",
|
||||
"version": "10.21.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry-internal/browser-utils/-/browser-utils-10.21.0.tgz",
|
||||
"integrity": "sha512-QRHpCBheLd/88Z2m3ABMriV0MweW+pcGKuVsH61/UdziKcQLdoQpOSvGg0/0CuqFm2UjL7237ZzLdZrWaCOlfQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@sentry/core": "9.5.0"
|
||||
"@sentry/core": "10.21.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@sentry-internal/feedback": {
|
||||
"version": "9.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-9.5.0.tgz",
|
||||
"integrity": "sha512-p+yOTufEYHP1RLwkD+aZwpCNS4/2l6t4uHgphjYrEC2U/U2mtZQh+EvlBAt0wY/eiKC4/acPNrF5yFD/4A7a0A==",
|
||||
"version": "10.21.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-10.21.0.tgz",
|
||||
"integrity": "sha512-6SnRR2FiW6TMwCE0PqbueHkkpeVnjOjz00R+/mX25Dp1U5BU5TzbXHzn9Y4wKnaD3Rzz4+nnzVkpHAOL3SppGw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@sentry/core": "9.5.0"
|
||||
"@sentry/core": "10.21.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@sentry-internal/replay": {
|
||||
"version": "9.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry-internal/replay/-/replay-9.5.0.tgz",
|
||||
"integrity": "sha512-fBBNimElAnu865HT3MJ6xH2P26KvkZvAYt+yRrWr+x5zS5KvjBYUPsSI+F0FTE14XmLW9q7DlNUl5iAZhXSy3g==",
|
||||
"version": "10.21.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry-internal/replay/-/replay-10.21.0.tgz",
|
||||
"integrity": "sha512-5tfiKZJzZf9+Xk8SyvoC4ZEVLNmjBZZEaKhVyNo53CLWUWfWOqDc3DB9fj85i/yHFQ0ImdRnaPBc0CIeN00CcA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@sentry-internal/browser-utils": "9.5.0",
|
||||
"@sentry/core": "9.5.0"
|
||||
"@sentry-internal/browser-utils": "10.21.0",
|
||||
"@sentry/core": "10.21.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@sentry-internal/replay-canvas": {
|
||||
"version": "9.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-9.5.0.tgz",
|
||||
"integrity": "sha512-W7MS7/9Z8uP2i0pbndxqz2VcGlFPc7Bv6gCoxRdGIWUWSBS9rsRbryO0sM0PwwuHt2mQtWMqwjYykcR441RBRA==",
|
||||
"version": "10.21.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-10.21.0.tgz",
|
||||
"integrity": "sha512-TOLo5mAjJSOuJId8Po44d1hwJ5bIZDtRSoupWpYWqLw1tuUh1tc4vqID11ZXsw9pBzjVIK653BPDX/z/9+Um+Q==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@sentry-internal/replay": "9.5.0",
|
||||
"@sentry/core": "9.5.0"
|
||||
"@sentry-internal/replay": "10.21.0",
|
||||
"@sentry/core": "10.21.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@sentry/browser": {
|
||||
"version": "9.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-9.5.0.tgz",
|
||||
"integrity": "sha512-HYSPW8GjknuYykJgOialKFyWg7ldmrbD1AKTIhksqdsNXLER07YeVWFAbe+xSYa1ZwwC8/s6vQJP9ZOoH1BaVg==",
|
||||
"version": "10.21.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-10.21.0.tgz",
|
||||
"integrity": "sha512-z/63bUFBQkTfJ5ElhWTYvomz+gZ1GsoH16v4/RGoPY5qZgYxcVO3fkp0opnu3gcbXS0ZW7TLRiHpqhvipDdP6g==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@sentry-internal/browser-utils": "9.5.0",
|
||||
"@sentry-internal/feedback": "9.5.0",
|
||||
"@sentry-internal/replay": "9.5.0",
|
||||
"@sentry-internal/replay-canvas": "9.5.0",
|
||||
"@sentry/core": "9.5.0"
|
||||
"@sentry-internal/browser-utils": "10.21.0",
|
||||
"@sentry-internal/feedback": "10.21.0",
|
||||
"@sentry-internal/replay": "10.21.0",
|
||||
"@sentry-internal/replay-canvas": "10.21.0",
|
||||
"@sentry/core": "10.21.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@sentry/core": {
|
||||
"version": "9.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/core/-/core-9.5.0.tgz",
|
||||
"integrity": "sha512-NMqyFdyg26ECAfnibAPKT8vvAt4zXp4R7dYtQnwJKhEJEVkgAshcNYeJ2D95ZLMVOqlqhTtTPnw1vqf+v9ePZg==",
|
||||
"version": "10.21.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/core/-/core-10.21.0.tgz",
|
||||
"integrity": "sha512-/+gpOOb2Wr1UbW59WKqNAVVIqFz9FjtUJuPtVh4UanxGCfavMPaKpFzSlaEKJSKDkiCQgANP4O2y8Y5Bh3tvEA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@sentry/react": {
|
||||
"version": "9.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/react/-/react-9.5.0.tgz",
|
||||
"integrity": "sha512-ixOlKuMxWKSK73u41vY2wQNkQpZJo4fwRkA6r4oy745ldcwhGlOy/TMACdotbHCn4ULC86rVZN5r49mH6SV5+w==",
|
||||
"version": "10.21.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/react/-/react-10.21.0.tgz",
|
||||
"integrity": "sha512-BSCGKkepg9QPJRS8AUjtSAFd4lYJLmz3+P+oehViEHQDtRqqmXbVIBLhqwPc05KvRGIl4/kIDjyfDuHCFCJigQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@sentry/browser": "9.5.0",
|
||||
"@sentry/core": "9.5.0",
|
||||
"@sentry/browser": "10.21.0",
|
||||
"@sentry/core": "10.21.0",
|
||||
"hoist-non-react-statics": "^3.3.2"
|
||||
},
|
||||
"engines": {
|
||||
@@ -2197,9 +2217,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@types/lodash": {
|
||||
"version": "4.17.16",
|
||||
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.16.tgz",
|
||||
"integrity": "sha512-HX7Em5NYQAXKW+1T+FiuG27NGwzJfCX3s1GjOa7ujxZa52kjJLOr4FUxT+giF6Tgxv1e+/czV/iTtBw27WTU9g==",
|
||||
"version": "4.17.17",
|
||||
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.17.tgz",
|
||||
"integrity": "sha512-RRVJ+J3J+WmyOTqnz3PiBLA501eKwXl2noseKOrNo/6+XEHjTAxO4xHvxQB6QuNm+s4WRbn6rSiap8+EA+ykFQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/lodash.mergewith": {
|
||||
@@ -2236,13 +2256,13 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "22.13.10",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.10.tgz",
|
||||
"integrity": "sha512-I6LPUvlRH+O6VRUqYOcMudhaIdUVWfsjnZavnsraHvpBwaEyMN29ry+0UVJhImYL16xsscu0aske3yA+uPOWfw==",
|
||||
"version": "24.9.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.9.1.tgz",
|
||||
"integrity": "sha512-QoiaXANRkSXK6p0Duvt56W208du4P9Uye9hWLWgGMDTEoKPhuenzNcC4vGUmrNkiOKTlIrBoyNQYNpSwfEZXSg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"undici-types": "~6.20.0"
|
||||
"undici-types": "~7.16.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/parse-json": {
|
||||
@@ -2258,9 +2278,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/react": {
|
||||
"version": "18.3.18",
|
||||
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.18.tgz",
|
||||
"integrity": "sha512-t4yC+vtgnkYjNSKlFx1jkAhH8LgTo2N/7Qvi83kdEaUtMDiwpbLAktKDaAMlRcJ5eSxZkH74eEGt1ky31d7kfQ==",
|
||||
"version": "18.3.26",
|
||||
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.26.tgz",
|
||||
"integrity": "sha512-RFA/bURkcKzx/X9oumPG9Vp3D3JUgus/d0b67KB0t5S/raciymilkOa66olh78MUI92QLbEJevO7rvqU/kjwKA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/prop-types": "*",
|
||||
@@ -2268,9 +2288,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@types/react-big-calendar": {
|
||||
"version": "1.16.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/react-big-calendar/-/react-big-calendar-1.16.1.tgz",
|
||||
"integrity": "sha512-pDHFcVWx+BvZbX6U39R4l8c9930vKnfx+09lf4W8r8HuxBDLzGk7Q63ncBmqqnQImEFNDKfwa6MDyu90cfzJ2A==",
|
||||
"version": "1.16.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/react-big-calendar/-/react-big-calendar-1.16.3.tgz",
|
||||
"integrity": "sha512-CR+5BKMhlr/wPgsp+sXOeNKNkoU1h/+6H1XoWuL7xnurvzGRQv/EnM8jPS9yxxBvXI8pjQBaJcI7RTSGiewG/Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -2280,9 +2300,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@types/react-dom": {
|
||||
"version": "18.3.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.5.tgz",
|
||||
"integrity": "sha512-P4t6saawp+b/dFrUr2cvkVsfvPguwsxtH6dNIYRllMsefqFzkZk5UIjzyDOv5g1dXIPdG4Sp1yCR4Z6RCUsG/Q==",
|
||||
"version": "18.3.7",
|
||||
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.7.tgz",
|
||||
"integrity": "sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
@@ -2682,9 +2702,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/brace-expansion": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
|
||||
"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
|
||||
"integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -3112,9 +3132,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/cookie": {
|
||||
"version": "0.6.0",
|
||||
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz",
|
||||
"integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==",
|
||||
"version": "0.7.2",
|
||||
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz",
|
||||
"integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
@@ -3242,15 +3262,15 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/dayjs": {
|
||||
"version": "1.11.13",
|
||||
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz",
|
||||
"integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==",
|
||||
"version": "1.11.18",
|
||||
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.18.tgz",
|
||||
"integrity": "sha512-zFBQ7WFRvVRhKcWoUh+ZA1g2HVgUbsZm9sbddh8EC5iv93sui8DVVz1Npvz+r6meo9VKfa8NyLWBsQK1VvIKPA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/debug": {
|
||||
"version": "4.4.0",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz",
|
||||
"integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==",
|
||||
"version": "4.4.1",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz",
|
||||
"integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ms": "^2.1.3"
|
||||
@@ -3398,9 +3418,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/dotenv": {
|
||||
"version": "16.4.7",
|
||||
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.7.tgz",
|
||||
"integrity": "sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==",
|
||||
"version": "17.2.3",
|
||||
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.2.3.tgz",
|
||||
"integrity": "sha512-JVUnt+DUIzu87TABbhPmNfVdBDt18BLOWjMUFJMSi/Qqg7NTYtabbvSNJGOJ7afbRuv9D/lngizHtP7QyLQ+9w==",
|
||||
"dev": true,
|
||||
"license": "BSD-2-Clause",
|
||||
"engines": {
|
||||
@@ -3556,9 +3576,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/es-module-lexer": {
|
||||
"version": "1.5.4",
|
||||
"resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.5.4.tgz",
|
||||
"integrity": "sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==",
|
||||
"version": "1.7.0",
|
||||
"resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz",
|
||||
"integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
@@ -4094,13 +4114,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/framer-motion": {
|
||||
"version": "12.5.0",
|
||||
"resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-12.5.0.tgz",
|
||||
"integrity": "sha512-buPlioFbH9/W7rDzYh1C09AuZHAk2D1xTA1BlounJ2Rb9aRg84OXexP0GLd+R83v0khURdMX7b5MKnGTaSg5iA==",
|
||||
"version": "12.23.24",
|
||||
"resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-12.23.24.tgz",
|
||||
"integrity": "sha512-HMi5HRoRCTou+3fb3h9oTLyJGBxHfW+HnNE25tAXOvVx/IvwMHK0cx7IR4a2ZU6sh3IX1Z+4ts32PcYBOqka8w==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"motion-dom": "^12.5.0",
|
||||
"motion-utils": "^12.5.0",
|
||||
"motion-dom": "^12.23.23",
|
||||
"motion-utils": "^12.23.6",
|
||||
"tslib": "^2.4.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
@@ -4204,6 +4224,16 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/generator-function": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/generator-function/-/generator-function-2.0.1.tgz",
|
||||
"integrity": "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/generic-names": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/generic-names/-/generic-names-4.0.0.tgz",
|
||||
@@ -4805,14 +4835,15 @@
|
||||
}
|
||||
},
|
||||
"node_modules/is-generator-function": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.0.tgz",
|
||||
"integrity": "sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ==",
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.2.tgz",
|
||||
"integrity": "sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"call-bound": "^1.0.3",
|
||||
"get-proto": "^1.0.0",
|
||||
"call-bound": "^1.0.4",
|
||||
"generator-function": "^2.0.0",
|
||||
"get-proto": "^1.0.1",
|
||||
"has-tostringtag": "^1.0.2",
|
||||
"safe-regex-test": "^1.1.0"
|
||||
},
|
||||
@@ -6528,18 +6559,18 @@
|
||||
}
|
||||
},
|
||||
"node_modules/motion-dom": {
|
||||
"version": "12.5.0",
|
||||
"resolved": "https://registry.npmjs.org/motion-dom/-/motion-dom-12.5.0.tgz",
|
||||
"integrity": "sha512-uH2PETDh7m+Hjd1UQQ56yHqwn83SAwNjimNPE/kC+Kds0t4Yh7+29rfo5wezVFpPOv57U4IuWved5d1x0kNhbQ==",
|
||||
"version": "12.23.23",
|
||||
"resolved": "https://registry.npmjs.org/motion-dom/-/motion-dom-12.23.23.tgz",
|
||||
"integrity": "sha512-n5yolOs0TQQBRUFImrRfs/+6X4p3Q4n1dUEqt/H58Vx7OW6RF+foWEgmTVDhIWJIMXOuNNL0apKH2S16en9eiA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"motion-utils": "^12.5.0"
|
||||
"motion-utils": "^12.23.6"
|
||||
}
|
||||
},
|
||||
"node_modules/motion-utils": {
|
||||
"version": "12.5.0",
|
||||
"resolved": "https://registry.npmjs.org/motion-utils/-/motion-utils-12.5.0.tgz",
|
||||
"integrity": "sha512-+hFFzvimn0sBMP9iPxBa9OtRX35ZQ3py0UHnb8U29VD+d8lQ8zH3dTygJWqK7av2v6yhg7scj9iZuvTS0f4+SA==",
|
||||
"version": "12.23.6",
|
||||
"resolved": "https://registry.npmjs.org/motion-utils/-/motion-utils-12.23.6.tgz",
|
||||
"integrity": "sha512-eAWoPgr4eFEOFfg2WjIsMoqJTW6Z8MTUCgn/GZ3VRpClWBdnbjryiA3ZSNLyxCTmCQx4RmYX6jX1iWHbenUPNQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/mri": {
|
||||
@@ -7382,9 +7413,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/prettier": {
|
||||
"version": "3.5.3",
|
||||
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.5.3.tgz",
|
||||
"integrity": "sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==",
|
||||
"version": "3.6.2",
|
||||
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.6.2.tgz",
|
||||
"integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
@@ -7582,9 +7613,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/react-big-calendar": {
|
||||
"version": "1.18.0",
|
||||
"resolved": "https://registry.npmjs.org/react-big-calendar/-/react-big-calendar-1.18.0.tgz",
|
||||
"integrity": "sha512-bGrCdyfnCGe2qnIdEoGkGgQdEFOiGO1Tq7RLkI1a2t8ZudyEAKekFtneO2/ltKQEQK6zH76YdJ7vR9UMyD+ULw==",
|
||||
"version": "1.19.4",
|
||||
"resolved": "https://registry.npmjs.org/react-big-calendar/-/react-big-calendar-1.19.4.tgz",
|
||||
"integrity": "sha512-FrvbDx2LF6JAWFD96LU1jjloppC5OgIvMYUYIPzAw5Aq+ArYFPxAjLqXc4DyxfsQDN0TJTMuS/BIbcSB7Pg0YA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.20.7",
|
||||
@@ -8607,9 +8638,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/tar-fs": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz",
|
||||
"integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==",
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.3.tgz",
|
||||
"integrity": "sha512-090nwYJDmlhwFwEW3QQl+vaNnxsO2yVsd45eTKRBzSzu+hlb1w2K9inVq5b0ngXuLVqQ4ApvsUHHnu/zQNkWAg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -8821,9 +8852,9 @@
|
||||
"license": "0BSD"
|
||||
},
|
||||
"node_modules/turbo-stream": {
|
||||
"version": "2.4.0",
|
||||
"resolved": "https://registry.npmjs.org/turbo-stream/-/turbo-stream-2.4.0.tgz",
|
||||
"integrity": "sha512-FHncC10WpBd2eOmGwpmQsWLDoK4cqsA/UT/GqNoaKOQnT8uzhtCbg3EoUDMvqpOSAI0S26mr0rkjzbOO6S3v1g==",
|
||||
"version": "2.4.1",
|
||||
"resolved": "https://registry.npmjs.org/turbo-stream/-/turbo-stream-2.4.1.tgz",
|
||||
"integrity": "sha512-v8kOJXpG3WoTN/+at8vK7erSzo6nW6CIaeOvNOkHQVDajfz1ZVeSxCbc6tOH4hrGZW7VUCV0TOXd8CPzYnYkrw==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/type-is": {
|
||||
@@ -8841,9 +8872,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/typescript": {
|
||||
"version": "5.8.2",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.2.tgz",
|
||||
"integrity": "sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ==",
|
||||
"version": "5.9.3",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
|
||||
"integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
|
||||
"devOptional": true,
|
||||
"license": "Apache-2.0",
|
||||
"bin": {
|
||||
@@ -8877,9 +8908,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/undici": {
|
||||
"version": "6.21.1",
|
||||
"resolved": "https://registry.npmjs.org/undici/-/undici-6.21.1.tgz",
|
||||
"integrity": "sha512-q/1rj5D0/zayJB2FraXdaWxbhWiNKDvu8naDT2dl1yTlvJp4BLtOcp2a5BvgGNQpYYJzau7tf1WgKv3b+7mqpQ==",
|
||||
"version": "6.22.0",
|
||||
"resolved": "https://registry.npmjs.org/undici/-/undici-6.22.0.tgz",
|
||||
"integrity": "sha512-hU/10obOIu62MGYjdskASR3CUAiYaFTtC9Pa6vHyf//mAipSvSQg6od2CnJswq7fvzNS3zJhxoRkgNVaHurWKw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
@@ -8887,9 +8918,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/undici-types": {
|
||||
"version": "6.20.0",
|
||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz",
|
||||
"integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==",
|
||||
"version": "7.16.0",
|
||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz",
|
||||
"integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
@@ -9288,9 +9319,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/vite": {
|
||||
"version": "5.4.14",
|
||||
"resolved": "https://registry.npmjs.org/vite/-/vite-5.4.14.tgz",
|
||||
"integrity": "sha512-EK5cY7Q1D8JNhSaPKVK4pwBFvaTmZxEnoKXLG/U9gmdDcihQGNzFlgIvaxezFR4glP1LsuiedwMBqCXH3wZccA==",
|
||||
"version": "5.4.19",
|
||||
"resolved": "https://registry.npmjs.org/vite/-/vite-5.4.19.tgz",
|
||||
"integrity": "sha512-qO3aKv3HoQC8QKiNSTuUM1l9o/XX3+c+VTgLHbJWHZGeTPVAg2XwazI9UWzoxjIJCGCV2zU60uqMzjeLZuULqA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
|
||||
38
package.json
38
package.json
@@ -9,33 +9,33 @@
|
||||
"publish": "remix build --sourcemap && wrangler pages deploy public"
|
||||
},
|
||||
"dependencies": {
|
||||
"@chakra-ui/react": "^2.10.6",
|
||||
"@chakra-ui/react": "^2.10.9",
|
||||
"@emotion/react": "^11.14.0",
|
||||
"@emotion/styled": "^11.14.0",
|
||||
"@fontsource-variable/plus-jakarta-sans": "^5.2.5",
|
||||
"@remix-run/cloudflare": "^2.16.0",
|
||||
"@remix-run/cloudflare-pages": "^2.16.0",
|
||||
"@remix-run/react": "^2.16.0",
|
||||
"@sentry/react": "^9.5.0",
|
||||
"@emotion/styled": "^11.14.1",
|
||||
"@fontsource-variable/plus-jakarta-sans": "^5.2.8",
|
||||
"@remix-run/cloudflare": "^2.17.1",
|
||||
"@remix-run/cloudflare-pages": "^2.17.1",
|
||||
"@remix-run/react": "^2.17.1",
|
||||
"@sentry/react": "^10.21.0",
|
||||
"aws4fetch": "^1.0.20",
|
||||
"dayjs": "^1.11.13",
|
||||
"framer-motion": "^12.5.0",
|
||||
"dayjs": "^1.11.18",
|
||||
"framer-motion": "^12.23.24",
|
||||
"react": "^18.3.1",
|
||||
"react-big-calendar": "^1.18.0",
|
||||
"react-big-calendar": "^1.19.4",
|
||||
"react-dom": "^18.3.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@remix-run/dev": "^2.16.0",
|
||||
"@types/node": "^22.13.10",
|
||||
"@types/react": "^18.3.18",
|
||||
"@types/react-big-calendar": "^1.16.1",
|
||||
"@types/react-dom": "^18.3.5",
|
||||
"dotenv": "^16.4.7",
|
||||
"prettier": "^3.5.3",
|
||||
"typescript": "^5.8.2"
|
||||
"@remix-run/dev": "^2.17.1",
|
||||
"@types/node": "^24.9.1",
|
||||
"@types/react": "^18.3.26",
|
||||
"@types/react-big-calendar": "^1.16.3",
|
||||
"@types/react-dom": "^18.3.7",
|
||||
"dotenv": "^17.2.3",
|
||||
"prettier": "^3.6.2",
|
||||
"typescript": "^5.9.3"
|
||||
},
|
||||
"overrides": {
|
||||
"@cloudflare/workers-types": "^4.20250311.0"
|
||||
"@cloudflare/workers-types": "^4.20251014.0"
|
||||
},
|
||||
"prettier": {
|
||||
"endOfLine": "auto"
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 57 KiB |
Reference in New Issue
Block a user