mirror of
https://github.com/Sendouc/sendou.ink.git
synced 2026-08-24 03:55:49 -05:00
Badge prize preview inside tags
This commit is contained in:
1
TODO.md
1
TODO.md
@@ -22,6 +22,7 @@ Calendar
|
||||
|
||||
## Other
|
||||
|
||||
- [x] badges inside tag?
|
||||
- [ ] Move "BADGE" tag resolving to DB?
|
||||
- [x] Tags selector can remove
|
||||
- [x] Calendar new title
|
||||
|
||||
@@ -136,7 +136,7 @@ const findAllBetweenTwoTimestampsStm = sql.prepare(`
|
||||
"CalendarEvent"."discordUrl",
|
||||
"CalendarEvent"."bracketUrl",
|
||||
"CalendarEvent"."tags",
|
||||
"CalendarEventDate"."id",
|
||||
"CalendarEventDate"."id" as "eventDateId",
|
||||
"CalendarEventDate"."eventId",
|
||||
"CalendarEventDate"."startTime",
|
||||
"User"."discordName",
|
||||
@@ -184,8 +184,9 @@ export function findAllBetweenTwoTimestamps({
|
||||
endTime: dateToDatabaseTimestamp(endTime),
|
||||
}) as Array<
|
||||
Pick<CalendarEvent, "name" | "discordUrl" | "bracketUrl" | "tags"> &
|
||||
Pick<CalendarEventDate, "id" | "eventId" | "startTime"> &
|
||||
Pick<User, "discordName" | "discordDiscriminator"> & {
|
||||
Pick<CalendarEventDate, "eventId" | "startTime"> & {
|
||||
eventDateId: CalendarEventDate["id"];
|
||||
} & Pick<User, "discordName" | "discordDiscriminator"> & {
|
||||
nthAppearance: number;
|
||||
} & { hasBadge: number }
|
||||
>;
|
||||
|
||||
@@ -11,7 +11,6 @@ import * as React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { z } from "zod";
|
||||
import { Avatar } from "~/components/Avatar";
|
||||
import { Badge } from "~/components/Badge";
|
||||
import { LinkButton } from "~/components/Button";
|
||||
import { Main } from "~/components/Main";
|
||||
import { db } from "~/db";
|
||||
@@ -26,7 +25,6 @@ import { discordFullName, makeTitle } from "~/utils/strings";
|
||||
import { calendarEditPage, resolveBaseUrl } from "~/utils/urls";
|
||||
import { actualNumber, id } from "~/utils/zod";
|
||||
import { Tags } from "./components/Tags";
|
||||
import allTags from "./tags.json";
|
||||
|
||||
export const links: LinksFunction = () => {
|
||||
return [{ rel: "stylesheet", href: styles }];
|
||||
@@ -63,12 +61,12 @@ export const loader = async ({ params, request }: LoaderArgs) => {
|
||||
|
||||
export default function CalendarEventPage() {
|
||||
const user = useUser();
|
||||
const { event } = useLoaderData<typeof loader>();
|
||||
const { event, badgePrizes } = useLoaderData<typeof loader>();
|
||||
const { i18n } = useTranslation();
|
||||
const isMounted = useIsMounted();
|
||||
|
||||
return (
|
||||
<Main className="stack md">
|
||||
<Main className="stack lg">
|
||||
<section className="stack sm">
|
||||
<div className="event__times">
|
||||
{event.startTimes.map((startTime, i) => (
|
||||
@@ -100,7 +98,7 @@ export default function CalendarEventPage() {
|
||||
<div className="stack md">
|
||||
<div className="stack xs">
|
||||
<h2>{event.name}</h2>
|
||||
<Tags tags={event.tags} />
|
||||
<Tags tags={event.tags} badges={badgePrizes} />
|
||||
</div>
|
||||
<div className="stack horizontal sm flex-wrap">
|
||||
{event.discordUrl ? (
|
||||
@@ -130,39 +128,16 @@ export default function CalendarEventPage() {
|
||||
</div>
|
||||
</section>
|
||||
<div className="stack sm">
|
||||
<div className="event__author-badges-container">
|
||||
<div className="event__author">
|
||||
<Avatar
|
||||
discordAvatar={event.discordAvatar}
|
||||
discordId={event.discordId}
|
||||
size="xs"
|
||||
/>
|
||||
{discordFullName(event)}
|
||||
</div>
|
||||
<PrizeBadges />
|
||||
<div className="event__author">
|
||||
<Avatar
|
||||
discordAvatar={event.discordAvatar}
|
||||
discordId={event.discordId}
|
||||
size="xs"
|
||||
/>
|
||||
{discordFullName(event)}
|
||||
</div>
|
||||
<div>{event.description}</div>
|
||||
</div>
|
||||
</Main>
|
||||
);
|
||||
}
|
||||
|
||||
function PrizeBadges() {
|
||||
const { badgePrizes } = useLoaderData<typeof loader>();
|
||||
|
||||
if (badgePrizes.length === 0) return null;
|
||||
|
||||
return (
|
||||
<div
|
||||
className="event__badges__container"
|
||||
style={{ color: allTags["BADGE"].color }}
|
||||
>
|
||||
Win!
|
||||
<div className="event__badges__gifs">
|
||||
{badgePrizes.map((badge) => (
|
||||
<Badge key={badge.code} badge={badge} size={26} isAnimated />
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,15 +1,19 @@
|
||||
import clsx from "clsx";
|
||||
import React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Badge } from "~/components/Badge";
|
||||
import { Button } from "~/components/Button";
|
||||
import { CrossIcon } from "~/components/icons/Cross";
|
||||
import type { CalendarEventTag } from "~/db/types";
|
||||
import type { Badge as BadgeType, CalendarEventTag } from "~/db/types";
|
||||
import allTags from "../tags.json";
|
||||
|
||||
export function Tags({
|
||||
tags,
|
||||
badges,
|
||||
onDelete,
|
||||
}: {
|
||||
tags: Array<CalendarEventTag>;
|
||||
badges?: Array<BadgeType>;
|
||||
/** Called when tag delete button clicked. If undefined delete buttons won't be shown. */
|
||||
onDelete?: (tag: CalendarEventTag) => void;
|
||||
}) {
|
||||
@@ -21,7 +25,10 @@ export function Tags({
|
||||
<ul className="calendar__event__tags">
|
||||
{tags.map((tag) => (
|
||||
<React.Fragment key={tag}>
|
||||
<li style={{ backgroundColor: allTags[tag].color }}>
|
||||
<li
|
||||
style={{ backgroundColor: allTags[tag].color }}
|
||||
className={clsx({ "calendar__event__badge-tag": tag === "BADGE" })}
|
||||
>
|
||||
{t(`tag.name.${tag}`)}
|
||||
{onDelete && (
|
||||
<Button
|
||||
@@ -34,6 +41,13 @@ export function Tags({
|
||||
data-cy="tag-delete-button"
|
||||
/>
|
||||
)}
|
||||
{tag === "BADGE" && badges && (
|
||||
<div className="calendar__event__tag-badges">
|
||||
{badges.map((badge) => (
|
||||
<Badge key={badge.id} badge={badge} size={20} isAnimated />
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</li>
|
||||
</React.Fragment>
|
||||
))}
|
||||
|
||||
@@ -115,7 +115,14 @@ function fetchEventsOfWeek(args: { week: number; year: number }) {
|
||||
// so we get all events of sunday even from US west coast perspective
|
||||
endTime.setHours(endTime.getHours() + 12);
|
||||
|
||||
return db.calendarEvents.findAllBetweenTwoTimestamps({ startTime, endTime });
|
||||
return db.calendarEvents
|
||||
.findAllBetweenTwoTimestamps({ startTime, endTime })
|
||||
.map((event) => ({
|
||||
...event,
|
||||
badgePrizes: event.tags.includes("BADGE")
|
||||
? db.calendarEvents.findBadgesById(event.eventId)
|
||||
: [],
|
||||
}));
|
||||
}
|
||||
|
||||
export default function CalendarPage() {
|
||||
@@ -290,7 +297,7 @@ function EventsList() {
|
||||
<div className="stack md">
|
||||
{events.map((calendarEvent, i) => {
|
||||
return (
|
||||
<React.Fragment key={calendarEvent.eventId}>
|
||||
<React.Fragment key={calendarEvent.eventDateId}>
|
||||
<section className="calendar__event main stack md">
|
||||
<div className="stack sm">
|
||||
<div
|
||||
@@ -329,7 +336,10 @@ function EventsList() {
|
||||
) : null}
|
||||
</h2>
|
||||
</Link>
|
||||
<Tags tags={calendarEvent.tags} />
|
||||
<Tags
|
||||
tags={calendarEvent.tags}
|
||||
badges={calendarEvent.badgePrizes}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="calendar__event__bottom-info-container">
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"BADGE": {
|
||||
"color": "#FDFD96"
|
||||
"color": "#000"
|
||||
},
|
||||
"SPECIAL": {
|
||||
"color": "#CE93D8"
|
||||
|
||||
@@ -17,26 +17,6 @@
|
||||
height: 1.25rem;
|
||||
}
|
||||
|
||||
.event__author-badges-container {
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.event__badges__container {
|
||||
font-size: var(--fonts-xs);
|
||||
font-weight: var(--semi-bold);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.event__badges__gifs {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
padding: var(--s-2);
|
||||
background-color: var(--bg-badge);
|
||||
border-radius: var(--rounded);
|
||||
}
|
||||
|
||||
.event__author {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
@@ -551,10 +551,19 @@ dialog::backdrop {
|
||||
padding-inline: var(--s-1-5);
|
||||
}
|
||||
|
||||
.calendar__event__badge-tag {
|
||||
color: var(--badge-text);
|
||||
}
|
||||
|
||||
.calendar__event__tag-delete-button {
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
.calendar__event__tag-badges {
|
||||
display: flex;
|
||||
margin-inline-start: var(--s-1);
|
||||
}
|
||||
|
||||
.calendar__event__tag-delete-button > svg {
|
||||
width: 0.85rem !important;
|
||||
color: var(--black-text);
|
||||
|
||||
Reference in New Issue
Block a user