event info

This commit is contained in:
Kalle (Sendou)
2021-03-28 00:14:55 +02:00
parent 8a00c60a14
commit a3410ca3bf
3 changed files with 201 additions and 15 deletions

View File

@@ -1,27 +1,85 @@
import { Button } from "@chakra-ui/button";
import { Trans } from "@lingui/macro";
import { useState } from "react";
import { Input } from "@chakra-ui/input";
import { Box } from "@chakra-ui/layout";
import { t, Trans } from "@lingui/macro";
import SubText from "components/common/SubText";
import { useMyTheme } from "hooks/common";
import { Fragment, useState } from "react";
import { trpc } from "utils/trpc";
import EventInfo from "./EventInfo";
import { EventModal } from "./EventModal";
export default function CalendarPage() {
const { gray } = useMyTheme();
const events = trpc.useQuery(["calendar.events"], { enabled: false });
const [modalIsOpen, setModalIsOpen] = useState(false);
const [filter, setFilter] = useState("");
console.log("events", events.data);
let lastPrintedWeek: number | null = null;
const thisWeekNumber = getWeekNumber(new Date());
return (
<div>
<Button size="sm" onClick={() => setModalIsOpen(true)}>
<Trans>Add event</Trans>
</Button>
{modalIsOpen && (
<EventModal
onClose={() => setModalIsOpen(false)}
event={false}
refetchQuery={events.refetch}
/>
)}
</div>
<>
<div>
<Button size="sm" onClick={() => setModalIsOpen(true)}>
<Trans>Add event</Trans>
</Button>
{modalIsOpen && (
<EventModal
onClose={() => setModalIsOpen(false)}
event={false}
refetchQuery={events.refetch}
/>
)}
</div>
<Input
value={filter}
onChange={(e) => setFilter(e.target.value)}
m="3rem 0 2rem"
/>
{(events.data ?? []).map((event) => {
const weekNumber = getWeekNumber(event.date);
const printWeekHeader = weekNumber !== lastPrintedWeek;
if (printWeekHeader) {
lastPrintedWeek = weekNumber;
}
return (
<Fragment key={event.id}>
{printWeekHeader && (
<Box my={10}>
<SubText>
Week {weekNumber}{" "}
{thisWeekNumber === weekNumber && <>({t`This week`})</>}
</SubText>
</Box>
)}
<div>
<EventInfo event={event} />
</div>
</Fragment>
);
})}
<Box color={gray}>All events listed in your local time:</Box>
</>
);
}
function getWeekNumber(d: Date) {
// Copy date so don't modify original
d = new Date(Date.UTC(d.getFullYear(), d.getMonth(), d.getDate()));
// Set to nearest Thursday: current date + 4 - current day number
// Make Sunday's day number 7
d.setUTCDate(d.getUTCDate() + 4 - (d.getUTCDay() || 7));
// Get first day of year
const yearStart = new Date(Date.UTC(d.getUTCFullYear(), 0, 1));
// Calculate full weeks to nearest Thursday
const weekNo = Math.ceil(
((d.getTime() - yearStart.getTime()) / 86400000 + 1) / 7
);
// Return array of year and week number
return weekNo;
}

View File

@@ -0,0 +1,122 @@
import { Box, Button, Flex, Grid, Heading } from "@chakra-ui/react";
import Markdown from "components/common/Markdown";
import MyLink from "components/common/MyLink";
import UserAvatar from "components/common/UserAvatar";
import { useMyTheme, useUser } from "hooks/common";
import React, { useState } from "react";
import { FaDiscord } from "react-icons/fa";
import { FiClock, FiEdit, FiInfo } from "react-icons/fi";
import { ADMIN_ID } from "utils/constants";
import { Unpacked } from "utils/types";
import { Events } from "../service";
interface EventInfoProps {
event: Unpacked<Events>;
}
const TournamentInfo = ({ event }: EventInfoProps) => {
const {
secondaryBgColor,
themeColorHex,
gray,
themeColorShade,
} = useMyTheme();
const [expanded, setExpanded] = useState(false);
const [showModal, setShowModal] = useState(false);
const poster = event.poster;
const [user] = useUser();
const canEdit = user?.id === poster.id || user?.id === ADMIN_ID;
return (
<Box
as="section"
rounded="lg"
overflow="hidden"
boxShadow="md"
bg={secondaryBgColor}
p="20px"
my={5}
>
<Box textAlign="center">
<Box>
<Heading fontFamily="'Rubik', sans-serif" size="lg">
{event.name}
</Heading>
<Flex
alignItems="center"
justifyContent="center"
color={gray}
mt="0.5rem"
>
<Box as={FiClock} mr="0.5em" color={themeColorShade} />
{/* TODO */}
{event.date.toLocaleString("en", {
weekday: "long",
month: "long",
day: "numeric",
hour: "numeric",
minute: "numeric",
})}
</Flex>
<Flex
alignItems="center"
justifyContent="center"
color={gray}
mt="1.1rem"
mb="0.5rem"
>
<Box mr="0.5em">
<UserAvatar user={event.poster} size="sm" />
</Box>{" "}
<MyLink href={`/u/${poster.discordId}`} isColored={false}>
<Box>
{poster.username}#{poster.discriminator}
</Box>
</MyLink>
</Flex>
</Box>
<Grid
templateColumns={canEdit ? "1fr 1fr 1fr" : "1fr 1fr"}
gridColumnGap="1rem"
maxW={canEdit ? "32rem" : "24rem"}
mx="auto"
mt={6}
>
{/* TODO */}
<Button leftIcon={<FaDiscord />} size="sm" variant="outline">
Join Discord
</Button>
<Button
leftIcon={<FiInfo />}
size="sm"
onClick={() => setExpanded(!expanded)}
variant="outline"
>
View info
</Button>
{canEdit && (
<Button
leftIcon={<FiEdit />}
size="sm"
onClick={() => setShowModal(true)}
variant="outline"
>
Edit event
</Button>
)}
</Grid>
</Box>
{expanded && (
<Box mt="1rem" mx="0.5rem">
<Markdown value={event.description} />
</Box>
)}
</Box>
);
};
export default TournamentInfo;

View File

@@ -1,9 +1,15 @@
import { Prisma } from "@prisma/client";
import prisma from "prisma/client";
import { eventSchema } from "utils/validators/event";
import * as z from "zod";
export type Events = Prisma.PromiseReturnType<typeof events>;
const events = () => {
return prisma.calendarEvent.findMany({ where: { date: { gt: new Date() } } });
return prisma.calendarEvent.findMany({
where: { date: { gt: new Date() } },
include: { poster: true },
});
};
const addEvent = async ({