diff --git a/app/db/models/calendar/queries.server.ts b/app/db/models/calendar/queries.server.ts index c41c56661..0b1c02c68 100644 --- a/app/db/models/calendar/queries.server.ts +++ b/app/db/models/calendar/queries.server.ts @@ -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, diff --git a/app/db/models/calendar/upcomingEvents.sql b/app/db/models/calendar/upcomingEvents.sql new file mode 100644 index 000000000..4199055cb --- /dev/null +++ b/app/db/models/calendar/upcomingEvents.sql @@ -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 \ No newline at end of file diff --git a/app/routes/calendar/components/Tags.tsx b/app/routes/calendar/components/Tags.tsx index 8a6a7095a..4b47e5f43 100644 --- a/app/routes/calendar/components/Tags.tsx +++ b/app/routes/calendar/components/Tags.tsx @@ -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; diff --git a/app/routes/calendar/index.tsx b/app/routes/calendar/index.tsx index bba3901f0..4c52ceadd 100644 --- a/app/routes/calendar/index.tsx +++ b/app/routes/calendar/index.tsx @@ -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() { diff --git a/app/routes/index.tsx b/app/routes/index.tsx index 4ae82eadf..49b96a70d 100644 --- a/app/routes/index.tsx +++ b/app/routes/index.tsx @@ -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() { ))}

Upcoming events

- {data.recentWinners.map((result) => ( -
{result.eventName}
+ {data.upcomingEvents.map((event) => ( + + + ))} ); diff --git a/app/styles/front-page.css b/app/styles/front-page.css index 3753d7c6a..caab7ef53 100644 --- a/app/styles/front-page.css +++ b/app/styles/front-page.css @@ -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); diff --git a/public/locales/en/calendar.json b/public/locales/en/calendar.json index e92f78838..fcf1ebc79 100644 --- a/public/locales/en/calendar.json +++ b/public/locales/en/calendar.json @@ -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.", diff --git a/public/locales/en/common.json b/public/locales/en/common.json index 44d7484b8..160b1a7e3 100644 --- a/public/locales/en/common.json +++ b/public/locales/en/common.json @@ -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" }