Skip to content

Commit

Permalink
events work
Browse files Browse the repository at this point in the history
  • Loading branch information
c0repwn3r committed Feb 21, 2024
1 parent 7a22ac2 commit ac5a781
Show file tree
Hide file tree
Showing 5 changed files with 245 additions and 38 deletions.
14 changes: 14 additions & 0 deletions src/lib/date.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
export function humanReadableDate(d: Date): string {
// Sat Feb 17, 2024, 18:00 (EST)
let options: Intl.DateTimeFormatOptions = {
weekday: "short",
year: "numeric",
month: "short",
day: "numeric",
hour: "2-digit",
minute: "2-digit",
timeZoneName: "short",
};

return new Intl.DateTimeFormat("en-US", options).format(d);
}
74 changes: 53 additions & 21 deletions src/routes/dashboard/vaccs/[id]/events/+page.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,38 +54,33 @@ export const actions: Actions = {
);
}

// combine the datetimes

let startDate = form.data.startDate.split("T")[0];
let startTime = String(form.data.startTime).padStart(4, "0");
let startHour = startTime.slice(0, 2);
let startMinute = startTime.slice(2);
let start = `${startDate}T${startHour}:${startMinute}:00Z`;

let endDate = form.data.endDate.split("T")[0];
let endTime = String(form.data.endTime).padStart(4, "0");
let endHour = endTime.slice(0, 2);
let endMinute = endTime.slice(2);
let end = `${endDate}T${endHour}:${endMinute}:00Z`;

// generate the blurhash

const imageData = await getPixels(form.data.bannerUrl);
const data = Uint8ClampedArray.from(imageData.data);
const blurhash = encode(data, imageData.width, imageData.height, 4, 4);

// combine the datetimes
let startDate = new Date(form.data.startDate);
let start_hour = parseInt(
String(form.data.startTime).padStart(4, "0").slice(0, 2),
);
let start_minute = parseInt(
String(form.data.startTime).padStart(4, "0").slice(2),
);
startDate.setHours(start_hour, start_minute);

let endDate = new Date(form.data.endDate);
let end_hour = parseInt(
String(form.data.endTime).padStart(4, "0").slice(0, 2),
);
let end_minute = parseInt(
String(form.data.endTime).padStart(4, "0").slice(2),
);
endDate.setHours(end_hour, end_minute);

await prisma.event.create({
data: {
id: ulid(),
name: form.data.name,
hostId: event.params.id,
start: startDate,
end: endDate,
start: start,
end: end,
description: form.data.description,
bannerUrl: form.data.bannerUrl,
bannerBlurHash: blurhash,
Expand All @@ -99,4 +94,41 @@ export const actions: Actions = {
form,
};
},
setVisibility: async (event) => {
let { user, roles } = await loadUserData(event.cookies);

if (
!can(
roles,
event.params.id,
user.vaccId,
`vacc.${event.params.id}.events.manage`,
)
) {
return redirect(
307,
`/dashboard/vaccs/${event.params.id}/`,
{ message: "You don't have permission to do that.", type: "error" },
event.cookies,
);
}

let data = await event.request.formData();

if (!data.has("eventId") || !data.has("public")) {
return { success: false };
} else {
let id = data.get("eventId")!.toString();
let isPublic = data.get("public")!.toString() === "true";
await prisma.event.update({
where: {
id
},
data: {
public: isPublic
}
});
return { success: true };
}
}
};
131 changes: 114 additions & 17 deletions src/routes/dashboard/vaccs/[id]/events/+page.svelte
Original file line number Diff line number Diff line change
@@ -1,22 +1,80 @@
<script lang="ts">
import type { PageData } from "./$types";
import { Plus } from "lucide-svelte";
import { MoreHorizontal, Plus } from "lucide-svelte";
import { Button } from "$lib/components/ui/button";
import { can } from "$lib/perms/can";
import * as Dialog from "$lib/components/ui/dialog";
import CreateEventForm from "./create-event-form.svelte";
import { toast } from "svelte-sonner";
import * as Table from "$lib/components/ui/table";
import Image from "$lib/components/Image.svelte";
import { humanReadableDate } from "$lib/date.js";
import { page } from "$app/stores";
import CertForm from "../roster/cert-form.svelte";
import * as DropdownMenu from "$lib/components/ui/dropdown-menu";
import { writable } from "svelte/store";
import {createRender, createTable, Render, Subscribe} from "svelte-headless-table";
import DataTableBanner from "./data-table-banner.svelte";
import DataTableActions from "./data-table-actions.svelte";
export let data: PageData;
let createDialogOpen = false;
let canManageEvents = can(
data.roles,
data.vacc_id,
data.user.vaccId,
`vacc.${data.vacc_id}.events.manage`,
);
let store = writable(data.events);
$: $store = data.events;
const table = createTable(store);
const columns = table.createColumns([
table.column({
accessor: (i) => i,
header: "Banner",
cell: ({ value }) => {
return createRender(DataTableBanner, { eventId: value.id, bannerUrl: value.bannerUrl, blurhash: value.bannerBlurHash })
}
}),
table.column({
accessor: "name",
header: "Name",
}),
table.column({
accessor: "start",
header: "Starts",
cell: ({ value }) => {
return humanReadableDate(value);
}
}),
table.column({
accessor: "end",
header: "Ends",
cell: ({ value }) => {
return humanReadableDate(value);
}
}),
table.column({
accessor: (e) => e,
header: "Actions",
cell: ({ value }) => {
return createRender(DataTableActions, { event: value, canManageEvents })
}
}),
]);
const { headerRows, pageRows, tableAttrs, tableBodyAttrs } =
table.createViewModel(columns);
</script>

<div class="flex items-center justify-between">
<h2 class="text-3xl font-bold tracking-tight">Upcoming Events</h2>
{#if can(data.roles, data.vacc_id, data.user.vaccId, `vacc.${data.vacc_id}.events.manage`)}
{#if canManageEvents}
<Button
on:click={() => {
createDialogOpen = true;
Expand All @@ -27,32 +85,71 @@
{/if}
</div>

<Table.Root {...$tableAttrs}>
<Table.Header>
{#each $headerRows as headerRow}
<Subscribe rowAttrs={headerRow.attrs()}>
<Table.Row>
{#each headerRow.cells as cell (cell.id)}
<Subscribe attrs={cell.attrs()} let:attrs props={cell.props()}>
<Table.Head {...attrs}>
<Render of={cell.render()} />
</Table.Head>
</Subscribe>
{/each}
</Table.Row>
</Subscribe>
{/each}
</Table.Header>
<Table.Body {...$tableBodyAttrs}>
{#each $pageRows as row (row.id)}
<Subscribe rowAttrs={row.attrs()} let:rowAttrs>
<Table.Row {...rowAttrs}>
{#each row.cells as cell (cell.id)}
<Subscribe attrs={cell.attrs()} let:attrs>
<Table.Cell {...attrs}>
<Render of={cell.render()} />
</Table.Cell>
</Subscribe>
{/each}
</Table.Row>
</Subscribe>
{/each}
</Table.Body>
</Table.Root>

<!--
<Table.Root>
<Table.Header>
<Table.Row>
<Table.Head>Banner</Table.Head>
<Table.Head class="w-min">Banner</Table.Head>
<Table.Head>Name</Table.Head>
<Table.Head>Time</Table.Head>
<Table.Head>Start</Table.Head>
<Table.Head>End</Table.Head>
{#if canManageEvents}
<Table.Head>Actions</Table.Head>
{/if}
</Table.Row>
</Table.Header>
<Table.Body>
{#each data.events as event}
<Table.Row>
<Table.Cell>
<Image
width="480px"
class="rounded"
src={event.bannerUrl}
blurhash={event.bannerBlurHash}
style="aspect-ratio: 16/9;"
alt="" />
</Table.Cell>
<Table.Cell>{event.name}</Table.Cell>
<Table.Cell>{event.start} to {event.end}</Table.Cell>
</Table.Row>
{#if event.public || canManageEvents}
<Table.Row>
<Table.Cell>
</Table.Cell>
<Table.Cell>{event.name}</Table.Cell>
<Table.Cell>{humanReadableDate(event.start)}</Table.Cell>
<Table.Cell>{humanReadableDate(event.end)}</Table.Cell>
{#if canManageEvents}
{/if}
</Table.Row>
{/if}
{/each}
</Table.Body>
</Table.Root>
-->

{#if can(data.roles, data.vacc_id, data.user.vaccId, `vacc.${data.vacc_id}.events.manage`)}
<Dialog.Root bind:open={createDialogOpen}>
Expand Down
46 changes: 46 additions & 0 deletions src/routes/dashboard/vaccs/[id]/events/data-table-actions.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<script lang="ts">
import * as DropdownMenu from "$lib/components/ui/dropdown-menu";
import type {Event} from "@prisma/client";
import {MoreHorizontal} from "lucide-svelte";
import {Button} from "$lib/components/ui/button";
import {toast} from "svelte-sonner";
export let event: Event;
export let canManageEvents: boolean;
</script>

<DropdownMenu.Root>
<DropdownMenu.Trigger asChild let:builder>
<Button
variant="ghost"
builders={[builder]}
size="icon"
class="relative w-8 h-8 p-0">
<span class="sr-only">Open menu</span>
<MoreHorizontal class="w-4 h-4" />
</Button>
</DropdownMenu.Trigger>
<DropdownMenu.Content>
<DropdownMenu.Group>
<DropdownMenu.Label>Actions</DropdownMenu.Label>
<DropdownMenu.Item
on:click={() => {navigator.clipboard.writeText(event.id); toast.success("Event ID copied to clipboard");}}>
Copy ID
</DropdownMenu.Item>
{#if canManageEvents}
<DropdownMenu.Separator />
{#if event.public}
<DropdownMenu.Item>Make Private</DropdownMenu.Item>
{:else}
<DropdownMenu.Item>Make Public</DropdownMenu.Item>
{/if}
<DropdownMenu.Item>
Edit
</DropdownMenu.Item>
<DropdownMenu.Item class="text-red-500 data-[highlighted]:bg-red-500/30 data-[highlighted]:text-red-500">
Delete
</DropdownMenu.Item>
{/if}
</DropdownMenu.Group>
</DropdownMenu.Content>
</DropdownMenu.Root>
18 changes: 18 additions & 0 deletions src/routes/dashboard/vaccs/[id]/events/data-table-banner.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<script lang="ts">
import {page} from "$app/stores";
import Image from "$lib/components/Image.svelte";
export let eventId: string;
export let bannerUrl: string;
export let blurhash: string;
</script>

<a href="/dashboard/vaccs/{$page.params.id}/events/{eventId}/">
<Image
width="480px"
class="rounded"
src={bannerUrl}
{blurhash}
style="aspect-ratio: 16/9;"
alt="" />
</a>

0 comments on commit ac5a781

Please sign in to comment.