mirror of
https://github.com/Sendouc/sendou.ink.git
synced 2026-09-13 22:56:05 -05:00
Front page upcomig events initial
This commit is contained in:
@@ -30,6 +30,7 @@ import startTimesOfRangeSql from "./startTimesOfRange.sql";
|
||||
import findBadgesByEventIdSql from "./findBadgesByEventId.sql";
|
||||
import eventsToReportSql from "./eventsToReport.sql";
|
||||
import recentWinnersSql from "./recentWinners.sql";
|
||||
import upcomingEventsSql from "./upcomingEvents.sql";
|
||||
|
||||
const createStm = sql.prepare(createSql);
|
||||
const updateStm = sql.prepare(updateSql);
|
||||
@@ -327,11 +328,10 @@ export function findAllBetweenTwoTimestamps({
|
||||
} & { hasBadge: number }
|
||||
>;
|
||||
|
||||
return rows.map(addTagArray);
|
||||
return rows.map(addTagArray).map(addBadges);
|
||||
}
|
||||
|
||||
const findByIdStm = sql.prepare(findByIdSql);
|
||||
|
||||
export function findById(id: CalendarEvent["id"]) {
|
||||
const [firstRow, ...rest] = findByIdStm.all({ id }) as Array<
|
||||
Pick<
|
||||
@@ -361,6 +361,32 @@ export function findById(id: CalendarEvent["id"]) {
|
||||
});
|
||||
}
|
||||
|
||||
const upcomingEventsStm = sql.prepare(upcomingEventsSql);
|
||||
export function upcomingEvents() {
|
||||
const rows = upcomingEventsStm.all({
|
||||
now: dateToDatabaseTimestamp(new Date()),
|
||||
}) as Array<{
|
||||
eventId: CalendarEvent["id"];
|
||||
eventName: CalendarEvent["name"];
|
||||
tags: CalendarEvent["tags"];
|
||||
startTime: CalendarEventDate["startTime"];
|
||||
hasBadge: number;
|
||||
}>;
|
||||
|
||||
return rows.map(addTagArray).map(addBadges);
|
||||
}
|
||||
|
||||
function addBadges<
|
||||
T extends { eventId: CalendarEvent["id"]; tags?: CalendarEvent["tags"] }
|
||||
>(arg: T) {
|
||||
return {
|
||||
...arg,
|
||||
badgePrizes: arg.tags?.includes("BADGE")
|
||||
? findBadgesByEventId(arg.eventId)
|
||||
: [],
|
||||
};
|
||||
}
|
||||
|
||||
const startTimesOfRangeStm = sql.prepare(startTimesOfRangeSql);
|
||||
export function startTimesOfRange({
|
||||
startTime,
|
||||
|
||||
24
app/db/models/calendar/upcomingEvents.sql
Normal file
24
app/db/models/calendar/upcomingEvents.sql
Normal file
@@ -0,0 +1,24 @@
|
||||
select
|
||||
"CalendarEvent"."id" as "eventId",
|
||||
"CalendarEvent"."name" as "eventName",
|
||||
"CalendarEvent"."tags",
|
||||
"CalendarEventDate"."startTime",
|
||||
exists (
|
||||
select
|
||||
1
|
||||
from
|
||||
"CalendarEventBadge"
|
||||
where
|
||||
"CalendarEventBadge"."eventId" = "CalendarEvent"."id"
|
||||
) as "hasBadge"
|
||||
from
|
||||
"CalendarEventDate"
|
||||
inner join "CalendarEvent" on "CalendarEvent"."id" = "CalendarEventDate"."eventId"
|
||||
where
|
||||
"CalendarEventDate"."startTime" > @now
|
||||
group by
|
||||
"CalendarEventDate"."eventId"
|
||||
order by
|
||||
"CalendarEventDate"."startTime" asc
|
||||
limit
|
||||
3
|
||||
@@ -17,7 +17,7 @@ export function Tags({
|
||||
/** Called when tag delete button clicked. If undefined delete buttons won't be shown. */
|
||||
onDelete?: (tag: CalendarEventTag) => void;
|
||||
}) {
|
||||
const { t } = useTranslation("calendar");
|
||||
const { t } = useTranslation();
|
||||
|
||||
if (tags.length === 0) return null;
|
||||
|
||||
|
||||
@@ -120,14 +120,7 @@ function fetchEventsOfWeek(args: { week: number; year: number }) {
|
||||
startTime.setHours(startTime.getHours() - 12);
|
||||
endTime.setHours(endTime.getHours() + 12);
|
||||
|
||||
return db.calendarEvents
|
||||
.findAllBetweenTwoTimestamps({ startTime, endTime })
|
||||
.map((event) => ({
|
||||
...event,
|
||||
badgePrizes: event.tags.includes("BADGE")
|
||||
? db.calendarEvents.findBadgesByEventId(event.eventId)
|
||||
: [],
|
||||
}));
|
||||
return db.calendarEvents.findAllBetweenTwoTimestamps({ startTime, endTime });
|
||||
}
|
||||
|
||||
export default function CalendarPage() {
|
||||
|
||||
@@ -8,6 +8,7 @@ import styles from "~/styles/front-page.css";
|
||||
import { databaseTimestampToDate } from "~/utils/dates";
|
||||
import { discordFullName } from "~/utils/strings";
|
||||
import { calendarEventPage, userPage } from "~/utils/urls";
|
||||
import { Tags } from "./calendar/components/Tags";
|
||||
|
||||
export const links: LinksFunction = () => {
|
||||
return [{ rel: "stylesheet", href: styles }];
|
||||
@@ -15,7 +16,7 @@ export const links: LinksFunction = () => {
|
||||
|
||||
export const loader = () => {
|
||||
return json({
|
||||
upcomingEvents: [],
|
||||
upcomingEvents: db.calendarEvents.upcomingEvents(),
|
||||
recentWinners: db.calendarEvents.recentWinners(),
|
||||
});
|
||||
};
|
||||
@@ -79,8 +80,23 @@ function CalendarPeek() {
|
||||
</Event>
|
||||
))}
|
||||
<h2>Upcoming events</h2>
|
||||
{data.recentWinners.map((result) => (
|
||||
<div key={result.eventId}>{result.eventName}</div>
|
||||
{data.upcomingEvents.map((event) => (
|
||||
<Event
|
||||
key={event.eventId}
|
||||
eventId={event.eventId}
|
||||
eventName={event.eventName}
|
||||
// xxx: this and the buddy need to not be there before mount
|
||||
startTimeString={databaseTimestampToDate(
|
||||
event.startTime
|
||||
).toLocaleString(i18n.language, {
|
||||
day: "numeric",
|
||||
month: "numeric",
|
||||
hour: "numeric",
|
||||
minute: "numeric",
|
||||
})}
|
||||
>
|
||||
<Tags tags={event.tags} badges={event.badgePrizes} />
|
||||
</Event>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
font-size: var(--fonts-sm);
|
||||
grid-template-areas: "name secondary" "content content";
|
||||
grid-template-columns: 1fr 1fr;
|
||||
row-gap: var(--s-1);
|
||||
}
|
||||
|
||||
.front__event-name {
|
||||
@@ -47,6 +48,7 @@
|
||||
|
||||
.front__event-winners {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
padding: 0;
|
||||
font-size: var(--fonts-xxs);
|
||||
gap: var(--s-3);
|
||||
|
||||
@@ -41,15 +41,6 @@
|
||||
"week.last": "Last",
|
||||
"week.week": "Week",
|
||||
|
||||
"tag.name.BADGE": "Badge prizes",
|
||||
"tag.name.SPECIAL": "Special rules",
|
||||
"tag.name.ART": "Art prizes",
|
||||
"tag.name.MONEY": "Money prizes",
|
||||
"tag.name.REGION": "Region locked",
|
||||
"tag.name.LOW": "Skill cap",
|
||||
"tag.name.COUNT": "Entry limit",
|
||||
"tag.name.LAN": "LAN",
|
||||
"tag.name.QUALIFIER": "Qualifier",
|
||||
"tag.desc.BADGE": "Winner of this event gets a sendou.ink badge.",
|
||||
"tag.desc.SPECIAL": "Ruleset that differ from the standard e.g. limited what weapons can be used.",
|
||||
"tag.desc.ART": "You can win art by playing in this tournament.",
|
||||
|
||||
@@ -27,5 +27,15 @@
|
||||
|
||||
"forms.name": "Name",
|
||||
"forms.description": "Description",
|
||||
"forms.errors.title": "Following errors need to be fixed"
|
||||
"forms.errors.title": "Following errors need to be fixed",
|
||||
|
||||
"tag.name.BADGE": "Badge prizes",
|
||||
"tag.name.SPECIAL": "Special rules",
|
||||
"tag.name.ART": "Art prizes",
|
||||
"tag.name.MONEY": "Money prizes",
|
||||
"tag.name.REGION": "Region locked",
|
||||
"tag.name.LOW": "Skill cap",
|
||||
"tag.name.COUNT": "Entry limit",
|
||||
"tag.name.LAN": "LAN",
|
||||
"tag.name.QUALIFIER": "Qualifier"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user