Banner on calendar page to notify about reporting

This commit is contained in:
Kalle
2022-08-12 22:52:55 +03:00
parent bc599e0c60
commit 8269288cb2
7 changed files with 109 additions and 3 deletions

View File

@@ -17,7 +17,7 @@ Calendar
- [x] Add winners page
- [ ] E2E test add winners page
- [x] Winners on the event info page
- [ ] There should be a banner on the list page if you have past tournaments to report
- [x] There should be a banner on the list page if you have past tournaments to report
- [x] On the user page tab showing past results
- [ ] Translations

16
app/components/Alert.tsx Normal file
View File

@@ -0,0 +1,16 @@
import type * as React from "react";
import { AlertIcon } from "./icons/Alert";
export function Alert({
children,
textClassName,
}: {
children: React.ReactNode;
textClassName?: string;
}) {
return (
<div className="alert">
<AlertIcon /> <div className={textClassName}>{children}</div>
</div>
);
}

View File

@@ -502,3 +502,36 @@ export function findBadgesById(eventId: CalendarEvent["id"]) {
Pick<Badge, "id" | "code" | "hue" | "displayName">
>;
}
const eventsToReportStm = sql.prepare(`
select
"CalendarEvent"."id",
"CalendarEvent"."name",
(select max("startTime")
from "CalendarEventDate"
where "eventId" = "CalendarEvent"."id") as "startTime"
from "CalendarEvent"
where
"CalendarEvent"."authorId" = $authorId
and
"startTime" > $lowerLimitTime
and
"startTime" < $upperLimitTime
and
"CalendarEvent"."participantCount" is null
`);
export function eventsToReport(authorId?: CalendarEvent["authorId"]) {
if (!authorId) return [];
const oneMonthAgo = new Date();
oneMonthAgo.setMonth(oneMonthAgo.getMonth() - 1);
return (
eventsToReportStm.all({
authorId,
upperLimitTime: dateToDatabaseTimestamp(new Date()),
lowerLimitTime: dateToDatabaseTimestamp(oneMonthAgo),
}) as Array<Pick<CalendarEvent, "id" | "name">>
).map((row) => ({ id: row.id, name: row.name }));
}

View File

@@ -8,10 +8,11 @@ import React from "react";
import { Flipped, Flipper } from "react-flip-toolkit";
import { useTranslation } from "react-i18next";
import { z } from "zod";
import { Alert } from "~/components/Alert";
import { LinkButton } from "~/components/Button";
import { db } from "~/db";
import { useIsMounted } from "~/hooks/useIsMounted";
import { useUser } from "~/modules/auth";
import { getUser, useUser } from "~/modules/auth";
import { i18next } from "~/modules/i18n";
import styles from "~/styles/calendar.css";
import { joinListToNaturalString } from "~/utils/arrays";
@@ -22,7 +23,7 @@ import {
} from "~/utils/dates";
import { discordFullName, makeTitle } from "~/utils/strings";
import type { Unpacked } from "~/utils/types";
import { resolveBaseUrl } from "~/utils/urls";
import { calendarReportWinnersPage, resolveBaseUrl } from "~/utils/urls";
import { actualNumber } from "~/utils/zod";
import { Tags } from "./components/Tags";
@@ -55,6 +56,7 @@ const loaderSearchParamsSchema = z.object({
});
export const loader = async ({ request }: LoaderArgs) => {
const user = await getUser(request);
const t = await i18next.getFixedT(request);
const url = new URL(request.url);
const parsedParams = loaderSearchParamsSchema.safeParse({
@@ -87,6 +89,7 @@ export const loader = async ({ request }: LoaderArgs) => {
}),
weeks: closeByWeeks({ week: displayedWeek, year: displayedYear }),
events: fetchEventsOfWeek({ week: displayedWeek, year: displayedYear }),
eventsToReport: db.calendarEvents.eventsToReport(user?.id),
title: makeTitle([`Week ${displayedWeek}`, t("pages.calendar")]),
});
};
@@ -143,6 +146,7 @@ export default function CalendarPage() {
return (
<main className="stack lg">
<WeekLinks />
<EventsToReport />
<div className="stack md">
{user && (
<LinkButton to="new" className="calendar__add-new-button" tiny>
@@ -287,6 +291,28 @@ function getEventsCountPerWeek(
return result;
}
function EventsToReport() {
const data = useLoaderData<typeof loader>();
if (data.eventsToReport.length === 0) return null;
return (
<Alert textClassName="calendar__events-to-report">
You can report results for{" "}
{data.eventsToReport.map((event, i) => (
<React.Fragment key={event.id}>
<Link to={calendarReportWinnersPage(event.id)}>{event.name}</Link>
{i === data.eventsToReport.length - 1
? ""
: i === data.eventsToReport.length - 2
? " and "
: ", "}
</React.Fragment>
))}
</Alert>
);
}
function EventsList({
events,
}: {

View File

@@ -85,6 +85,10 @@
line-height: 0.8;
}
.calendar__events-to-report {
line-height: 1.25rem;
}
.calendar__events-container {
background-color: var(--bg-lighter);
}

View File

@@ -480,12 +480,35 @@ dialog::backdrop {
background-color: var(--theme-transparent);
}
.alert {
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: center;
background-color: var(--theme-info-transparent);
border-radius: var(--rounded);
color: var(--text);
font-size: var(--fonts-sm);
font-weight: var(--semi-bold);
gap: var(--s-2);
line-height: 0.75;
margin-inline: auto;
padding-block: var(--s-1-5);
padding-inline-end: var(--s-4);
padding-inline-start: var(--s-3);
}
.avatar {
background-color: var(--bg-lighter);
background-image: url("/svg/background-pattern.svg");
border-radius: 50%;
}
.alert > svg {
height: 1.75rem;
fill: var(--theme-info);
}
.form-errors {
font-size: var(--fonts-sm);
}

View File

@@ -18,6 +18,8 @@
--theme-warning: #c9c900;
--theme-success: #00a514;
--theme-success-transparent: #00a51452;
--theme-info: #1fb0d0;
--theme-info-transparent: #1fb0d052;
--theme: hsl(255deg 64% 63%);
--theme-vibrant: hsl(255deg 100% 81%);
--theme-transparent: hsl(255deg 66.7% 75% / 40%);
@@ -90,6 +92,8 @@
--theme-warning: #f5f587;
--theme-success: #a3ffae;
--theme-success-transparent: #a3ffae52;
--theme-info: #87cddc;
--theme-info-transparent: #87cddc52;
--theme: hsl(255deg 66.7% 75%);
--theme-vibrant: hsl(255deg 78% 65%);
--theme-transparent: hsl(255deg 66.7% 75% / 40%);