more brainstorming

This commit is contained in:
z1glr
2025-01-06 17:03:18 +00:00
parent 26030a5026
commit 9a7a80ac80
21 changed files with 2767 additions and 443 deletions

View File

@@ -0,0 +1,106 @@
import { useState } from "react";
import { Add } from "@carbon/icons-react";
import zustand, { EventData, Task, Tasks } from "../../Zustand";
import { Button } from "@nextui-org/button";
import { Checkbox, CheckboxGroup } from "@nextui-org/checkbox";
import { DatePicker } from "@nextui-org/date-picker";
import { getLocalTimeZone, now, ZonedDateTime } from "@internationalized/date";
import { Textarea } from "@nextui-org/input";
import {
Modal,
ModalBody,
ModalContent,
ModalFooter,
ModalHeader,
} from "@nextui-org/modal";
interface state {
date: ZonedDateTime;
description: string;
tasks: Task[];
}
export default function AddEvent(props: {
className?: string;
isOpen: boolean;
onOpenChange: (isOpen: boolean) => void;
}) {
const [state, setState] = useState<state>({
date: now(getLocalTimeZone()),
description: "",
tasks: [],
});
function addEvent() {
const eventData: EventData = {
date: state.date.toString(),
description: state.description,
id: zustand.getState().events.slice(-1)[0].id + 1,
tasks: {},
volunteers: {},
};
// add all the tasks
state.tasks.forEach((task) => {
eventData.tasks[task] = undefined;
});
zustand.getState().addEvent(eventData);
}
return (
<Modal
isOpen={props.isOpen}
shadow={"none" as "sm"} // somehow "none" isn't allowed
onOpenChange={props.onOpenChange}
backdrop="blur"
classNames={{
base: "bg-accent-5 ",
}}
>
<ModalContent>
<ModalHeader>
<h1 className="text-2xl">Add Event</h1>
</ModalHeader>
<ModalBody>
<DatePicker
label="Event date"
variant="bordered"
hideTimeZone
granularity="minute"
value={state.date}
onChange={(dt) => (!!dt ? setState({ ...state, date: dt }) : null)}
/>
<Textarea
variant="bordered"
placeholder="Description"
value={state.description}
onValueChange={(desc) => setState({ ...state, description: desc })}
/>
<CheckboxGroup
value={state.tasks}
onValueChange={(newTasks) =>
setState({ ...state, tasks: newTasks })
}
>
{Tasks.map((task, ii) => (
<div key={ii}>
<Checkbox value={task}>{task}</Checkbox>
</div>
))}
</CheckboxGroup>
</ModalBody>
<ModalFooter>
<Button
color="primary"
radius="full"
startContent={<Add size={32} />}
onPress={addEvent}
>
Add
</Button>
</ModalFooter>
</ModalContent>
</Modal>
);
}

View File

@@ -0,0 +1,50 @@
import { Card, CardBody, CardHeader } from "@nextui-org/card";
import { Divider } from "@nextui-org/divider";
import LocalDate from "./LocalDate";
import { EventData } from "@/Zustand";
export default function Event(props: EventData) {
return (
<Card
classNames={{
base: "bg-accent-4 w-64",
body: "flex flex-col gap-4",
}}
shadow="none"
>
<CardHeader>
<h3 className="bold mb-1 text-2xl">
<LocalDate
options={{
dateStyle: "short",
timeStyle: "short",
timeZone: "Europe/Berlin", // TODO: check with actual backend
}}
>
{props.date.toDate()}
</LocalDate>
</h3>
</CardHeader>
<Divider />
<CardBody>
<div>{props.description}</div>
<table>
<caption>
<h4>Task assignment</h4>
</caption>
<tbody>
{Object.entries(props.tasks).map(([task, person], ii) => (
<tr key={ii}>
<th className="pr-4 text-left">{task}</th>
<td>
{person ?? <span className="text-highlight">missing</span>}
</td>
</tr>
))}
</tbody>
</table>
</CardBody>
</Card>
);
}

View File

@@ -0,0 +1,16 @@
"use local";
import { DateFormatter } from "@/Zustand";
import { useLocale } from "@react-aria/i18n";
export default function LocalDate(props: {
children: Date;
className?: string;
options: Intl.DateTimeFormatOptions;
}) {
const formatter = new DateFormatter(useLocale().locale, props.options);
return (
<span className={props.className}>{formatter.format(props.children)}</span>
);
}