Platform-wide visual overhaul, team invites, analytics improvements, and deployment hardening
UI overhaul applying jury dashboard design patterns across all pages: - Stat cards with border-l-4 accent + icon pills on admin, observer, mentor, applicant dashboards and reports - Card section headers with color-coded icon pills throughout - Hover lift effects (translate-y + shadow) on cards and list items - Gradient progress bars (brand-teal to brand-blue) platform-wide - AnimatedCard stagger animations on all dashboard sections - Auth pages with gradient accent strip and polished icon containers - EmptyState component upgraded with rounded icon pill containers - Replaced AI-looking icons (Brain/Sparkles/Bot/Wand2/Cpu) with descriptive alternatives across 12 files - Removed gradient overlay from jury dashboard header - Quick actions restyled as card links with group hover effects Backend improvements: - Team member invite emails with account setup flow and notification logging - Analytics routers accept edition-wide queries (programId) in addition to roundId - Round detail endpoint returns inline progress data (eliminates extra getProgress call) - Award voting endpoints parallelized with Promise.all - Bulk invite supports optional sendInvitation flag - AwardVote composite index migration for query performance Infrastructure: - Docker entrypoint with migration retry loop (configurable retries/delay) - docker-compose pull_policy: always for automatic image refresh - Simplified deploy/update scripts using docker compose up -d --pull always - Updated deployment documentation Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -5,6 +5,7 @@ import Link from 'next/link'
|
||||
import type { Route } from 'next'
|
||||
import { usePathname } from 'next/navigation'
|
||||
import { signOut } from 'next-auth/react'
|
||||
import { useTranslations } from 'next-intl'
|
||||
import { cn } from '@/lib/utils'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import {
|
||||
@@ -33,7 +34,7 @@ import {
|
||||
Trophy,
|
||||
User,
|
||||
MessageSquare,
|
||||
Wand2,
|
||||
LayoutTemplate,
|
||||
} from 'lucide-react'
|
||||
import { getInitials } from '@/lib/utils'
|
||||
import { Logo } from '@/components/shared/logo'
|
||||
@@ -41,6 +42,7 @@ import { EditionSelector } from '@/components/shared/edition-selector'
|
||||
import { useEdition } from '@/contexts/edition-context'
|
||||
import { UserAvatar } from '@/components/shared/user-avatar'
|
||||
import { NotificationBell } from '@/components/shared/notification-bell'
|
||||
import { LanguageSwitcher } from '@/components/shared/language-switcher'
|
||||
import { useSession } from 'next-auth/react'
|
||||
import { trpc } from '@/lib/trpc/client'
|
||||
|
||||
@@ -120,7 +122,7 @@ const adminNavigation: NavItem[] = [
|
||||
{
|
||||
name: 'Apply Page',
|
||||
href: '/admin/programs',
|
||||
icon: Wand2,
|
||||
icon: LayoutTemplate,
|
||||
activeMatch: 'apply-settings',
|
||||
},
|
||||
{
|
||||
@@ -145,6 +147,7 @@ const roleLabels: Record<string, string> = {
|
||||
|
||||
export function AdminSidebar({ user }: AdminSidebarProps) {
|
||||
const pathname = usePathname()
|
||||
const tAuth = useTranslations('auth')
|
||||
const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false)
|
||||
const { status: sessionStatus } = useSession()
|
||||
const isAuthenticated = sessionStatus === 'authenticated'
|
||||
@@ -170,6 +173,7 @@ export function AdminSidebar({ user }: AdminSidebarProps) {
|
||||
<div className="fixed top-0 left-0 right-0 z-40 flex h-16 items-center justify-between border-b bg-card px-4 lg:hidden">
|
||||
<Logo showText textSuffix="Admin" />
|
||||
<div className="flex items-center gap-2">
|
||||
<LanguageSwitcher />
|
||||
<NotificationBell />
|
||||
<Button
|
||||
variant="ghost"
|
||||
@@ -204,7 +208,8 @@ export function AdminSidebar({ user }: AdminSidebarProps) {
|
||||
{/* Logo + Notification */}
|
||||
<div className="flex h-16 items-center justify-between border-b px-6">
|
||||
<Logo showText textSuffix="Admin" />
|
||||
<div className="hidden lg:block">
|
||||
<div className="hidden lg:flex items-center gap-1">
|
||||
<LanguageSwitcher />
|
||||
<NotificationBell />
|
||||
</div>
|
||||
</div>
|
||||
@@ -344,7 +349,7 @@ export function AdminSidebar({ user }: AdminSidebarProps) {
|
||||
className="flex cursor-pointer items-center gap-2.5 rounded-md px-2 py-2 text-destructive focus:bg-destructive/10 focus:text-destructive"
|
||||
>
|
||||
<LogOut className="h-4 w-4" />
|
||||
<span>Sign out</span>
|
||||
<span>{tAuth('signOut')}</span>
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
|
||||
Reference in New Issue
Block a user