diff --git a/full-stack/src/routes/group/mock.tsx b/full-stack/src/routes/group/mock.tsx new file mode 100644 index 0000000..d954c4e --- /dev/null +++ b/full-stack/src/routes/group/mock.tsx @@ -0,0 +1,335 @@ +import { createFileRoute } from '@tanstack/react-router'; +import { Archive, Crown, Filter, Moon, Sprout, Sun } from 'lucide-react'; +import { useState } from 'react'; +import { MembershipKind } from '@/_generated/prisma/enums'; +import { + Paragraph, + Subtitle, + Text, +} from '@/components/design-system/typography'; +import { + UserAvatar, + UserAvatarFallback, + type UserAvatarTier, +} from '@/components/design-system/user-avatar'; +import { Button } from '@/components/ui/button'; +import { cn } from '@/lib/utils'; +import { getInitials } from '@/utils/string'; + +export const Route = createFileRoute('/group/mock')({ + component: GroupProfilePage, +}); + +interface GroupRef { + id: string; + name: string; +} + +interface MemberData { + membershipId: string; + userId: string; + name: string; + kind: MembershipKind; + roleTitle?: string; + points: number | null; + tier?: UserAvatarTier; + isLeader: boolean; +} + +const KIND_LABEL: Record = { + ACTIVE: 'RENDES TAG', + NEWBIE: 'ÚJONC', + FORMER: 'ALUMNI', + ARCHIVED: 'ARCHIVÁLT', +}; + +const KIND_TEXT_CLASS: Record = { + ACTIVE: 'text-status-member', + NEWBIE: 'text-status-newbie', + FORMER: 'text-status-alumni', + ARCHIVED: 'text-status-alumni', +}; + +const OBJECTIVE_TEXT = + 'Mióta 2001 folyamatosan fejlesztünk webes alkalmazásokat az egyetemi közösség számára. A Pék-Next, a KonferenciaApp és számos további projekt fejlesztői vagyunk.'; + +const MOCK_MEMBERS: Array = [ + { + membershipId: 'mem-1', + userId: 'u-1', + name: 'Pekkaros Péter', + kind: MembershipKind.ACTIVE, + roleTitle: 'Körvezető', + points: 48, + tier: 'tier-2', + isLeader: true, + }, + { + membershipId: 'mem-2', + userId: 'u-2', + name: 'Backend Balázs', + kind: MembershipKind.ACTIVE, + points: 41, + tier: 'tier-1', + isLeader: false, + }, + { + membershipId: 'mem-3', + userId: 'u-3', + name: 'Kódoló Kata', + kind: MembershipKind.ACTIVE, + roleTitle: 'Frontend Lead', + points: 38, + isLeader: false, + }, + { + membershipId: 'mem-4', + userId: 'u-4', + name: 'Newbie Norbert', + kind: MembershipKind.NEWBIE, + roleTitle: 'Trainee', + points: null, + isLeader: false, + }, + { + membershipId: 'mem-5', + userId: 'u-5', + name: 'Old Olivér', + kind: MembershipKind.FORMER, + points: null, + isLeader: false, + }, +]; + +const MOCK_PARENTS: GroupRef[] = [ + { id: 'g-szakkoll', name: 'Simonyi Károly Szakkollégium' }, +]; +const CURRENT_GROUP: GroupRef = { id: 'g-kirdev', name: 'Kir-Dev' }; +const MOCK_CHILDREN: GroupRef[] = [ + { id: 'g-cmsch', name: 'CMSch Project' }, + { id: 'g-devops', name: 'DevOps Team' }, + { id: 'g-ci-2025s', name: 'Course Instructors 2025 Spring' }, +]; + +const FOUNDATION_YEAR = 2001; +const TOTAL_ACTIVITY = 12_450; +const SEMESTER_BADGE = 'Aktív szemeszter'; + +const POINTS_MAX = 50; + +function tierTone(tier: UserAvatarTier): { text: string; bar: string } { + if (tier === 'tier-2') { + return { + text: 'text-tier-2-start', + bar: 'bg-linear-to-r from-tier-2-start to-tier-2-end', + }; + } + if (tier === 'tier-1') { + return { + text: 'text-tier-1-start', + bar: 'bg-linear-to-r from-tier-1-start to-tier-1-end', + }; + } + return { text: 'text-indigo-400', bar: 'bg-indigo-400' }; +} + +function openMember(_member: MemberData) {} + +function MemberRow({ member }: { member: MemberData }) { + const tier = member.tier ?? 'unknown'; + const initials = getInitials(member.name); + const hasPoints = member.points !== null; + const tone = hasPoints ? tierTone(tier) : null; + const width = hasPoints + ? Math.round(((member.points ?? 0) / POINTS_MAX) * 100) + : 0; + + return ( + + ); +} + +function GroupProfilePage() { + const [theme, setTheme] = useState<'dark' | 'light'>('dark'); + const activeCount = MOCK_MEMBERS.filter( + (m) => m.kind !== MembershipKind.FORMER + ).length; + + return ( +
+
+ +
+ +
+
+
+ + {SEMESTER_BADGE} + +

+ {CURRENT_GROUP.name} +

+

+ Alapítva: {FOUNDATION_YEAR} • {OBJECTIVE_TEXT} +

+
+
+
+
+ Aktivitás +
+
+ {TOTAL_ACTIVITY.toLocaleString('en-US')} +
+
+
+
+ Tagok +
+
+ {MOCK_MEMBERS.length} +
+
+
+
+
+ +
+
+
+ {/*TODO org tree component*/} +
+ Struktúra +
    + {[...MOCK_PARENTS, CURRENT_GROUP, ...MOCK_CHILDREN].map( + (group) => ( +
  • + {group.name} +
  • + ) + )} +
+
+ +
+ Cél + + {OBJECTIVE_TEXT} + +
+
+ +
+
+
+ Tagok + + {activeCount} Aktív + +
+ +
+
+ {MOCK_MEMBERS.map((member) => ( + + ))} +
+
+
+
+
+ ); +} diff --git a/full-stack/src/styles.css b/full-stack/src/styles.css index 05b3c45..80cbabd 100644 --- a/full-stack/src/styles.css +++ b/full-stack/src/styles.css @@ -34,6 +34,9 @@ --tier-3-end: oklch(0.52 0.1 220); --tier-draft: oklch(0.7 0.06 240 / 60%); --tier-inactive: oklch(0.75 0.01 240); + --status-member: oklch(0.67 0.18 277); + --status-newbie: oklch(0.76 0.18 163); + --status-alumni: var(--muted-foreground); --background: oklch(1 0 0); --foreground: oklch(0.145 0 0); @@ -90,6 +93,9 @@ --tier-3-end: oklch(0.7 0.08 220); --tier-draft: oklch(0.5 0.08 240 / 60%); --tier-inactive: oklch(0.35 0.01 240); + --status-member: oklch(0.67 0.18 277); + --status-newbie: oklch(0.76 0.18 163); + --status-alumni: var(--muted-foreground); --background: oklch(0.145 0 0); --foreground: oklch(0.985 0 0); @@ -135,6 +141,8 @@ } :root { + --banner: oklch(0.2 0.04 255); + --space-page: 1rem; /* 16px */ --space-section: 1rem; /* 16px */ --space-card: 0.875rem; /* 14px */ @@ -198,8 +206,12 @@ --color-tier-3-end: var(--tier-3-end); --color-tier-draft: var(--tier-draft); --color-tier-inactive: var(--tier-inactive); + --color-status-member: var(--status-member); + --color-status-newbie: var(--status-newbie); + --color-status-alumni: var(--status-alumni); --color-glass: var(--glass); --color-glass-elevated: var(--glass-elevated); + --color-banner: var(--banner); --ease-out-expo: cubic-bezier(0.16, 1, 0.3, 1);