mirror of
https://github.com/Sendouc/sendou.ink.git
synced 2026-06-02 22:26:57 -05:00
Single event page initial
This commit is contained in:
parent
1294bac966
commit
51fdc6c7fb
|
|
@ -9,5 +9,6 @@ export const db = {
|
|||
plusSuggestions,
|
||||
plusVotes,
|
||||
badges,
|
||||
// xxx: rename to events.... or calendarEvents?
|
||||
calendar,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -35,3 +35,29 @@ export function findAllBetweenTwoTimestamps({
|
|||
Pick<User, "discordName" | "discordDiscriminator">
|
||||
>;
|
||||
}
|
||||
|
||||
const findByIdStm = sql.prepare(`
|
||||
select
|
||||
"CalendarEvent"."name",
|
||||
"CalendarEvent"."description",
|
||||
"CalendarEvent"."discordUrl",
|
||||
"CalendarEvent"."bracketUrl",
|
||||
"CalendarEventDate"."startTime",
|
||||
"CalendarEventDate"."eventId",
|
||||
"User"."discordName",
|
||||
"User"."discordDiscriminator",
|
||||
"User"."discordId",
|
||||
"User"."discordAvatar"
|
||||
from "CalendarEvent"
|
||||
join "CalendarEventDate" on "CalendarEvent"."id" = "CalendarEventDate"."eventId"
|
||||
join "User" on "CalendarEvent"."authorId" = "User"."id"
|
||||
where "CalendarEvent"."id" = $id
|
||||
`);
|
||||
|
||||
export function findById(id: CalendarEvent["id"]) {
|
||||
return findByIdStm.get({ id }) as Nullable<
|
||||
Pick<CalendarEvent, "name" | "description" | "discordUrl" | "bracketUrl"> &
|
||||
Pick<CalendarEventDate, "startTime" | "eventId"> &
|
||||
Pick<User, "discordName" | "discordDiscriminator">
|
||||
>;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ import shuffle from "just-shuffle";
|
|||
import { dateToDatabaseTimestamp } from "~/utils/dates";
|
||||
import capitalize from "just-capitalize";
|
||||
|
||||
const ADMIN_TEST_AVATAR = "fcfd65a3bea598905abb9ca25296816b";
|
||||
const ADMIN_TEST_AVATAR = "e424e1ba50d2019fdc4730d261e56c55";
|
||||
|
||||
const NZAP_TEST_DISCORD_ID = "455039198672453645";
|
||||
const NZAP_TEST_AVATAR = "f809176af93132c3db5f0a5019e96339"; // https://cdn.discordapp.com/avatars/455039198672453645/f809176af93132c3db5f0a5019e96339.webp?size=160
|
||||
|
|
|
|||
89
app/routes/calendar/$id.tsx
Normal file
89
app/routes/calendar/$id.tsx
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
import { json, type LinksFunction, type LoaderArgs } from "@remix-run/node";
|
||||
import { useLoaderData } from "@remix-run/react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { z } from "zod";
|
||||
import { LinkButton } from "~/components/Button";
|
||||
import { Main } from "~/components/Main";
|
||||
import { db } from "~/db";
|
||||
import { useIsMounted } from "~/hooks/useIsMounted";
|
||||
import { databaseTimestampToDate } from "~/utils/dates";
|
||||
import { notFoundIfFalsy } from "~/utils/remix";
|
||||
import { resolveBaseUrl } from "~/utils/urls";
|
||||
import { actualNumber, id } from "~/utils/zod";
|
||||
import styles from "~/styles/calendar-event.css";
|
||||
|
||||
export const links: LinksFunction = () => {
|
||||
return [{ rel: "stylesheet", href: styles }];
|
||||
};
|
||||
|
||||
export const loader = ({ params }: LoaderArgs) => {
|
||||
const parsedParams = z
|
||||
.object({ id: z.preprocess(actualNumber, id) })
|
||||
.parse(params);
|
||||
const event = notFoundIfFalsy(db.calendar.findById(parsedParams.id));
|
||||
|
||||
return json({
|
||||
event,
|
||||
});
|
||||
};
|
||||
|
||||
export default function CalendarEventPage() {
|
||||
const { event } = useLoaderData<typeof loader>();
|
||||
const { i18n } = useTranslation();
|
||||
const isMounted = useIsMounted();
|
||||
|
||||
// TODO: -> next user info with avatar
|
||||
// xxx: time doesn't take space, not taking in account many dates
|
||||
|
||||
return (
|
||||
<Main className="stack lg">
|
||||
<section className="stack sm">
|
||||
<div>
|
||||
<time
|
||||
className="event__time"
|
||||
dateTime={databaseTimestampToDate(event.startTime).toISOString()}
|
||||
>
|
||||
{isMounted
|
||||
? databaseTimestampToDate(event.startTime).toLocaleDateString(
|
||||
i18n.language,
|
||||
{
|
||||
hour: "numeric",
|
||||
minute: "numeric",
|
||||
day: "numeric",
|
||||
month: "long",
|
||||
weekday: "long",
|
||||
}
|
||||
)
|
||||
: null}
|
||||
</time>
|
||||
</div>
|
||||
<h2 className="calendar__event__title">{event.name}</h2>
|
||||
{event.discordUrl || event.bracketUrl ? (
|
||||
<div className="stack horizontal sm">
|
||||
{event.discordUrl ? (
|
||||
<LinkButton
|
||||
to={event.discordUrl}
|
||||
variant="outlined"
|
||||
tiny
|
||||
isExternal
|
||||
>
|
||||
Discord
|
||||
</LinkButton>
|
||||
) : null}
|
||||
{event.bracketUrl ? (
|
||||
<LinkButton
|
||||
to={event.bracketUrl}
|
||||
variant="outlined"
|
||||
tiny
|
||||
isExternal
|
||||
>
|
||||
{resolveBaseUrl(event.bracketUrl)}
|
||||
</LinkButton>
|
||||
) : null}
|
||||
</div>
|
||||
) : null}
|
||||
</section>
|
||||
<div>{event.description}</div>
|
||||
</Main>
|
||||
);
|
||||
}
|
||||
|
|
@ -114,6 +114,8 @@ export default function CalendarPage() {
|
|||
// dates/times on the server
|
||||
const isMounted = useIsMounted();
|
||||
|
||||
// xxx: scrolls down on page load?
|
||||
// xxx: instead calculate into object
|
||||
const datesRendered = new Set<string>();
|
||||
return (
|
||||
<main>
|
||||
|
|
|
|||
7
app/styles/calendar-event.css
Normal file
7
app/styles/calendar-event.css
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
.event__title {
|
||||
line-height: 1.35;
|
||||
}
|
||||
|
||||
.event__time {
|
||||
font-weight: var(--semi-bold);
|
||||
}
|
||||
|
|
@ -72,7 +72,7 @@
|
|||
}
|
||||
|
||||
.calendar__events-container {
|
||||
background-color: var(--theme-transparent-vibrant);
|
||||
background-color: var(--bg-lighter);
|
||||
margin-block-start: var(--s-8);
|
||||
}
|
||||
|
||||
|
|
@ -113,6 +113,7 @@
|
|||
color: var(--text);
|
||||
font-size: var(--fonts-xl);
|
||||
line-height: 1.35;
|
||||
margin-block: var(--s-1);
|
||||
}
|
||||
|
||||
.calendar__event__bottom-info-container {
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user