sendou.ink/components/calendar/EventInfo.tsx
Kalle 1589b84c4b
New layout (#427) closes #405
* side layout initial

* add elements to side nav

* side buttons links

* remove clog

* calendar page initial

* position sticky working

* x trends page initial

* new table

* same mode selector

* mobile friendly table

* no underline for nav links

* xsearch

* x trends page outlined

* sr initial

* relocate calendar components

* calendar fix flex

* topnav fancier look

* layout looking good edition

* relocate xtrends

* xtrends remove linecharts

* x trends new

* calender page new

* delete headbanner, new login

* remove calendar stuff from api

* rename stuff in utils

* fix user item margin

* new home page initial

* remove page concept

* no pointer xtrends

* remove xrank from app

* xtrends service

* move fa from app

* move plus

* maps tweaks

* new table for plus history

* navigational sidebar flex tweaks

* builds page

* analyzer

* user page

* free agents

* plans

* remove mx

* tweaks

* change layout to grid

* home page finalized

* mobile nav

* restrict main content width

* tweaks style

* language switcher

* container in css

* sticky nav

* use duplicate icons for now

* change mapsketch width to old

* chara tour vid

* borzoic icons
2021-04-21 17:26:50 +03:00

186 lines
5.9 KiB
TypeScript

import { Badge, Box, Button, Flex, Grid, Heading } from "@chakra-ui/react";
import Markdown from "components/common/Markdown";
import MyLink from "components/common/MyLink";
import OutlinedBox from "components/common/OutlinedBox";
import UserAvatar from "components/common/UserAvatar";
import { useMyTheme, useUser } from "hooks/common";
import Image from "next/image";
import React from "react";
import { FiClock, FiEdit, FiExternalLink } from "react-icons/fi";
import { Events } from "services/calendar";
import { DiscordIcon } from "utils/assets/icons";
import { ADMIN_ID, EVENT_FORMATS, TAGS } from "utils/constants";
import { Unpacked } from "utils/types";
const nameToImage = [
{ code: "tasl", name: "tasl" },
{ code: "lowink", name: "low ink" },
{ code: "lobstercrossfire", name: "lobster crossfire" },
{ code: "swimorsink", name: "swim or sink" },
{ code: "idtga", name: "it's dangerous to go alone" },
{ code: "rr", name: "reef rushdown" },
{ code: "tg", name: "testing grounds" },
{ code: "ut", name: "unnamed tournament" },
{ code: "kotc", name: "king of the castle" },
{ code: "zones", name: "area cup" },
{ code: "cb", name: "cloudburst" },
] as const;
/**
* Returns event logo image path based on the event name or undefined if no image saved for the event.
*/
export const eventImage = (eventName: string) => {
const eventNameLower = eventName.toLowerCase();
if (eventNameLower.startsWith("plus server")) {
return `/layout/plus.png`;
}
for (const { name, code } of nameToImage) {
if (eventNameLower.startsWith(name)) {
return `/events/${code}.png`;
}
}
return undefined;
};
interface EventInfoProps {
event: Unpacked<Events>;
edit: () => void;
}
const EventInfo = ({ event, edit }: EventInfoProps) => {
const { gray, themeColorShade } = useMyTheme();
const poster = event.poster;
const [user] = useUser();
const canEdit = user?.id === poster.id || user?.id === ADMIN_ID;
const imgSrc = eventImage(event.name);
return (
<OutlinedBox
my={4}
py={4}
data-cy={`event-info-section-${event.name
.toLowerCase()
.replace(/ /g, "-")}`}
>
<Box width="100%">
<Box textAlign="center">
<Box>
{imgSrc && <Image src={imgSrc} width={36} height={36} />}
<Heading size="lg">{event.name}</Heading>
{event.tags.length > 0 && (
<Flex flexWrap="wrap" justifyContent="center" mt={3} mb={2}>
{event.tags.map((tag) => {
const tagInfo = TAGS.find((tagObj) => tagObj.code === tag)!;
return (
<Badge key={tag} mx={1} bg={tagInfo.color} color="black">
{tagInfo.name}
</Badge>
);
})}
</Flex>
)}
<Grid
templateColumns={["1fr", "2fr 4fr 2fr"]}
placeItems="center flex-start"
gridRowGap="0.5rem"
maxW="32rem"
mx="auto"
mt={1}
mb={3}
>
<Flex placeItems="center" ml={[null, "auto"]} mx={["auto", null]}>
<Box
as={FiClock}
mr="0.5em"
color={themeColorShade}
justifySelf="flex-end"
/>
{/* TODO */}
<Box as="time" dateTime={event.date.toISOString()}>
{event.date.toLocaleString("en", {
hour: "numeric",
minute: "numeric",
})}
</Box>
</Flex>
<Flex placeItems="center" mx="auto">
<Box
as={FiExternalLink}
mr="0.5em"
color={themeColorShade}
justifySelf="flex-end"
/>
<MyLink href={event.eventUrl} isExternal>
{new URL(event.eventUrl).host}
</MyLink>
</Flex>
<Flex placeItems="center" mr={[null, "auto"]} mx={["auto", null]}>
<UserAvatar
user={event.poster}
size="sm"
justifySelf="flex-end"
mr={2}
/>
<MyLink href={`/u/${poster.discordId}`} isColored={false}>
<Box>
{poster.username}#{poster.discriminator}
</Box>
</MyLink>
</Flex>
</Grid>
</Box>
<Grid
templateColumns={["1fr", canEdit ? "1fr 1fr" : "1fr"]}
gridRowGap="1rem"
gridColumnGap="1rem"
maxW={["12rem", canEdit ? "24rem" : "12rem"]}
mx="auto"
mt={4}
>
{event.discordInviteUrl ? (
<MyLink href={event.discordInviteUrl} isExternal>
<Button
leftIcon={<DiscordIcon />}
size="sm"
variant="outline"
width="100%"
>
Join Discord
</Button>
</MyLink>
) : (
<div />
)}
{canEdit && (
<Button
leftIcon={<FiEdit />}
size="sm"
onClick={edit}
variant="outline"
data-cy={`edit-button-${event.name
.toLowerCase()
.replace(/ /g, "-")}`}
>
Edit event
</Button>
)}
</Grid>
</Box>
<Box mt={8} mx="0.5rem" wordBreak="break-word">
<Box color={gray} fontSize="small" mb={2}>
{EVENT_FORMATS.find((format) => format.code === event.format)!.name}
</Box>
<Markdown smallHeaders value={event.description} />
</Box>
</Box>
</OutlinedBox>
);
};
export default EventInfo;