diff --git a/apps/web/src/components/award-badge.tsx b/apps/web/src/components/award-badge.tsx index 24b4ccb..8f88971 100644 --- a/apps/web/src/components/award-badge.tsx +++ b/apps/web/src/components/award-badge.tsx @@ -1,26 +1,19 @@ -import { CrownIcon, MedalIcon } from 'lucide-react' - import { Badge } from '@/components/ui/badge' +import { awardIcon } from '@/components/award-mark' import { placeLabel } from '@/lib/format' import type { Place } from '@/lib/types' const styles = { - first: { - icon: CrownIcon, - className: 'border-amber-500/50 bg-amber-500/10 text-amber-600 dark:text-amber-400', - }, - 'runner-up': { - icon: MedalIcon, - className: 'border-slate-400/60 bg-slate-400/10 text-slate-600 dark:text-slate-300', - }, + first: 'border-award-first/50 bg-award-first/10 text-award-first', + 'runner-up': 'border-award-runner-up/60 bg-award-runner-up/10 text-award-runner-up', } as const export function AwardBadge({ place }: { place: Place | null }) { if (!place) return null - const { icon: Icon, className } = styles[place] + const Icon = awardIcon[place] return ( - + {placeLabel[place]} diff --git a/apps/web/src/components/award-mark.tsx b/apps/web/src/components/award-mark.tsx new file mode 100644 index 0000000..fbf850e --- /dev/null +++ b/apps/web/src/components/award-mark.tsx @@ -0,0 +1,54 @@ +import { CrownIcon, MedalIcon } from 'lucide-react' +import type { ReactNode } from 'react' + +import { placeLabel } from '@/lib/format' +import type { Place } from '@/lib/types' +import { cn } from '@/lib/utils' + +export const awardIcon = { + first: CrownIcon, + 'runner-up': MedalIcon, +} as const + +const tone = { + first: 'text-award-first', + 'runner-up': 'text-award-runner-up', +} as const + +export function AwardMark({ place, className }: { place: Place | null; className?: string }) { + if (!place) return null + const Icon = awardIcon[place] + + return ( + + + + ) +} + +export function AwardedAvatar({ + place, + children, + className, +}: { + place: Place | null + children: ReactNode + className?: string +}) { + return ( + + {children} + {place === 'first' && ( + + )} + {place === 'runner-up' && ( + + + + )} + + ) +} diff --git a/apps/web/src/components/brand/event-logo.tsx b/apps/web/src/components/brand/event-logo.tsx index 5f125a4..0e56f92 100644 --- a/apps/web/src/components/brand/event-logo.tsx +++ b/apps/web/src/components/brand/event-logo.tsx @@ -1,13 +1,19 @@ -import { cn } from '@/lib/utils' import onDark from '@/assets/hackmeridian-light.png' import onLight from '@/assets/hackmeridian-dark.png' -import { EVENT_NAME } from '@/lib/config' +import { EVENT_NAME, EVENT_URL } from '@/lib/config' +import { cn } from '@/lib/utils' export function EventLogo({ className }: { className?: string }) { return ( - <> - {EVENT_NAME} - {EVENT_NAME} - + + + + ) } diff --git a/apps/web/src/components/explorer/columns.tsx b/apps/web/src/components/explorer/columns.tsx index e36ad4c..fc4ed57 100644 --- a/apps/web/src/components/explorer/columns.tsx +++ b/apps/web/src/components/explorer/columns.tsx @@ -9,6 +9,7 @@ import { ProjectLink, } from '@/components/links' import { AwardBadge } from '@/components/award-badge' +import { AwardMark } from '@/components/award-mark' import { TierBadge } from '@/components/tier-badge' import { Badge } from '@/components/ui/badge' import { @@ -31,6 +32,7 @@ export const projectColumns: Column[] = [ cell: (row) => (
+ {row.country && {flagEmoji(row.country)}} {!row.full_name && no repo} diff --git a/apps/web/src/components/explorer/project-card.tsx b/apps/web/src/components/explorer/project-card.tsx index a64eaf1..1f3edf2 100644 --- a/apps/web/src/components/explorer/project-card.tsx +++ b/apps/web/src/components/explorer/project-card.tsx @@ -3,6 +3,7 @@ import { Link } from 'react-router' import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar' import { AwardBadge } from '@/components/award-badge' +import { AwardedAvatar } from '@/components/award-mark' import { TierBadge } from '@/components/tier-badge' import { TrackBadge } from '@/components/track-badge' import { Badge } from '@/components/ui/badge' @@ -27,12 +28,14 @@ export function ProjectCard({ project, commits }: { project: Project; commits?:
- - {project.owner_avatar && ( - - )} - {name.slice(0, 2).toUpperCase()} - + + + {project.owner_avatar && ( + + )} + {name.slice(0, 2).toUpperCase()} + +
+} + interface WaffleProps { projects: Project[] lens: Lens | null @@ -49,10 +56,12 @@ export function Waffle({ projects, lens, columns, delay = 0 }: WaffleProps) { ease: EASE_SPRING, }} className={cn( - 'block size-full rounded-sm', + 'grid size-full place-items-center rounded-sm', project.tier === 'verified' ? 'bg-primary' : 'bg-secondary', )} - /> + > + {project.award && } + @@ -60,6 +69,7 @@ export function Waffle({ projects, lens, columns, delay = 0 }: WaffleProps) { {name.slice(0, 2).toUpperCase()} {name} + {project.award && {placeLabel[project.award]}} {tierLabel[project.tier]} {project.language && ` ยท ${project.language}`} diff --git a/apps/web/src/index.css b/apps/web/src/index.css index 82ae925..907ede0 100644 --- a/apps/web/src/index.css +++ b/apps/web/src/index.css @@ -22,6 +22,9 @@ --color-chart-3: var(--chart-3); --color-chart-2: var(--chart-2); --color-chart-1: var(--chart-1); + --color-award-first: var(--award-first); + --color-award-runner-up: var(--award-runner-up); + --color-award-foreground: var(--award-foreground); --color-ring: var(--ring); --color-input: var(--input); --color-border: var(--border); @@ -119,6 +122,9 @@ --input: #d6d2c4; --ring: #fdda24; --chart-1: #fdda24; + --award-first: #c98f00; + --award-runner-up: #6b7585; + --award-foreground: #0f0f0f; --chart-2: #00a7b5; --chart-3: #b7ace8; --chart-4: #002e5d; @@ -183,6 +189,9 @@ --input: #1a1917; --ring: #fdda24; --chart-1: #fdda24; + --award-first: #f5c518; + --award-runner-up: #c4cad4; + --award-foreground: #0f0f0f; --chart-2: #00a7b5; --chart-3: #b7ace8; --chart-4: #d6d2c4; diff --git a/apps/web/src/lib/config.ts b/apps/web/src/lib/config.ts index 41f81c3..79c2bab 100644 --- a/apps/web/src/lib/config.ts +++ b/apps/web/src/lib/config.ts @@ -3,3 +3,4 @@ export const API_URL = (import.meta.env.VITE_API_URL ?? '').replace(/\/$/, '') export const REPO_URL = 'https://github.com/devodii/hackproof' export const EVENT_NAME = 'HackMeridian 2026' +export const EVENT_URL = 'https://www.hackmeridian.com/' diff --git a/apps/web/src/pages/project.tsx b/apps/web/src/pages/project.tsx index 751fea6..5e58c7a 100644 --- a/apps/web/src/pages/project.tsx +++ b/apps/web/src/pages/project.tsx @@ -9,6 +9,7 @@ import { ProjectSkeleton } from '@/components/page-skeletons' import { DetailError } from '@/components/query-state' import { Section } from '@/components/section' import { AwardBadge } from '@/components/award-badge' +import { AwardedAvatar } from '@/components/award-mark' import { TierBadge } from '@/components/tier-badge' import { TrackBadge } from '@/components/track-badge' import { Accordion } from '@/components/ui/accordion' @@ -53,12 +54,14 @@ export function ProjectPage() {
- - {project.owner_avatar && ( - - )} - {name.slice(0, 2).toUpperCase()} - + + + {project.owner_avatar && ( + + )} + {name.slice(0, 2).toUpperCase()} + +

{name}

{project.country && {flagEmoji(project.country)}}