Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
bfeb06c
feat: replaces theme toggle with settings button in header, initializ…
SengdowJones Jun 16, 2025
f6dc53f
feat: add mock tag section for settings
SengdowJones Jun 23, 2025
1993a07
Refactor settings page, add tag management, and update theme selector
cursoragent Jul 20, 2025
9dbfb5b
Refine UI styling for settings and tag manager with improved theming
cursoragent Jul 20, 2025
0e90bb4
Refactor settings page with custom profile management sections
cursoragent Jul 20, 2025
e14abd1
Enhance settings page with Clerk user profile and dynamic user info
cursoragent Jul 20, 2025
dfc3251
Refactor settings pages with dynamic routes and optimize user profile…
cursoragent Jul 20, 2025
fad12c5
Configure Next.js to allow remote images from Clerk
cursoragent Jul 20, 2025
60582f9
Enhance Clerk UserProfile styling across settings pages
cursoragent Jul 20, 2025
087f7a6
Remove Clerk user settings pages and simplify settings overview
cursoragent Jul 20, 2025
a9d7382
Refactor tag management UI with popover for edit and delete actions
cursoragent Jul 20, 2025
72c19ad
Enhance tag creation and edit UI with improved design and preview
cursoragent Jul 20, 2025
936ec63
Add stepper buttons for min days before item reuse input
cursoragent Jul 20, 2025
8f33f23
Fix number input styling to remove spin buttons in TagManager
cursoragent Jul 20, 2025
d90f27a
Refactor TagManager: use shared Tag component everywhere, streamline …
SengdowJones Jul 23, 2025
1e82903
feat(TagManager): align delete button left and action buttons right i…
SengdowJones Jul 24, 2025
20d69fd
fix: make Tag appearance consistent across app by using compact={false}
SengdowJones Jul 24, 2025
f7ea936
refactor: replace native confirm dialog with design system dialog
SengdowJones Jul 30, 2025
88917e9
feat: add keyboard navigation support for color selection
SengdowJones Jul 30, 2025
f5b1a69
refactor: eliminate type duplication in tag functions
SengdowJones Jul 30, 2025
50fe85c
feat: make tags more compact in outfit suggestions
SengdowJones Aug 1, 2025
f092aec
feat: update authenticated header navigation
SengdowJones Aug 1, 2025
ebe2c7d
feat: improve dark mode color consistency with transparent buttons
SengdowJones Aug 1, 2025
da6e62a
fix: resolve nested button hydration error in TagManager
SengdowJones Aug 1, 2025
2500b68
fix: align Settings page content with header elements
SengdowJones Aug 1, 2025
faea7b9
feat: add sign-out functionality and improve Settings page UX
SengdowJones Aug 1, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions hono/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion hono/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
},
"dependencies": {
"@clerk/backend": "^1.23.7",
"@hono/clerk-auth": "^2.0.0",
"@hono/clerk-auth": "^2.0.1",
"@hono/eslint-config": "^0.0.4",
"@hono/zod-validator": "^0.4.2",
"@neondatabase/serverless": "^0.10.4",
Expand Down
13 changes: 12 additions & 1 deletion next/next.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,17 @@ if (process.env.NODE_ENV === 'development') {
}

/** @type {import('next').NextConfig} */
const nextConfig = {};
const nextConfig = {
images: {
remotePatterns: [
{
protocol: 'https',
hostname: 'img.clerk.com',
port: '',
pathname: '/**',
},
],
},
};

export default nextConfig;
114 changes: 114 additions & 0 deletions next/src/app/(authenticated)/settings/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
'use client'

import { ThemeSelector } from "@/components/ui/theme-toggle"
import { Card, CardContent, CardHeader, CardTitle, CardDescription } from "@/components/ui/card"
import { TagManager } from "@/components/TagManager"
import { useUser, useClerk } from "@clerk/nextjs"
import Image from "next/image"
import { User, Monitor, LogOut } from "lucide-react"
import { Button } from "@/components/ui/button"

export default function SettingsPage() {
const { user } = useUser()
const { signOut } = useClerk()

const handleSignOut = async () => {
await signOut()
}

return (
<div className="max-w-4xl mx-auto py-10 space-y-8">
<div className="space-y-2">
<h1 className="text-3xl font-bold tracking-tight">Settings</h1>
<p className="text-muted-foreground">
Manage your preferences, customize your experience, and organize your wardrobe.
</p>
</div>

<div className="grid gap-6">
{/* Appearance Settings */}
<Card className="bg-card/80 shadow-md border border-border">
<CardHeader>
<CardTitle className="flex items-center gap-2 text-lg font-semibold">
<Monitor className="h-5 w-5" />
Appearance
</CardTitle>
<CardDescription>
Customize how Shafa looks and feels across all your devices.
</CardDescription>
</CardHeader>
<CardContent>
<div className="space-y-3">
<div>
<h4 className="text-sm font-medium mb-3">Theme Preference</h4>
<ThemeSelector />
</div>
<p className="text-xs text-muted-foreground">
Choose your preferred theme. System will automatically match your device&apos;s theme.
</p>
</div>
</CardContent>
</Card>

{/* Tag Management */}
<TagManager />

{/* User Profile */}
<Card className="bg-card/80 shadow-md border border-border">
<CardHeader>
<CardTitle className="flex items-center gap-2 text-lg font-semibold">
<User className="h-5 w-5" />
Account & Profile
</CardTitle>
<CardDescription>
Manage your account information and access advanced profile settings.
</CardDescription>
</CardHeader>
<CardContent>
<div className="space-y-6">
{/* Current User Info */}
{user && (
<div className="p-4 rounded-lg border bg-background/50">
<div className="flex items-center justify-between gap-4">
<div className="flex items-center gap-4 min-w-0 flex-1">
{user.imageUrl ? (
<Image
src={user.imageUrl}
alt="Profile"
width={48}
height={48}
className="w-12 h-12 rounded-full object-cover flex-shrink-0"
/>
) : (
<div className="w-12 h-12 rounded-full bg-primary/20 flex items-center justify-center flex-shrink-0">
<User className="h-6 w-6 text-primary" />
</div>
)}
<div className="min-w-0 flex-1">
<h3 className="font-medium text-foreground truncate">
{user.fullName || user.firstName}
</h3>
<p className="text-sm text-muted-foreground truncate">
{user.primaryEmailAddress?.emailAddress}
</p>
</div>
</div>
<Button
variant="outline"
size="sm"
onClick={handleSignOut}
className="flex-shrink-0 bg-transparent hover:bg-red-500/10 border-red-400/40 text-red-400 hover:text-red-300 hover:border-red-400/60 transition-colors"
>
<LogOut className="mr-1.5 h-3.5 w-3.5" />
Sign out
</Button>
</div>
</div>
)}
</div>
</CardContent>
</Card>
</div>
</div>
)
}
25 changes: 17 additions & 8 deletions next/src/components/AuthenticatedHeader.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
'use client'

import { useState, useEffect, memo } from 'react'
import { useState, useEffect } from 'react'
import { Button } from '@/components/ui/button'
import { Shirt, Sparkles, Calendar, Flame, Layers } from 'lucide-react'
import { Shirt, Sparkles, Layers, Settings } from 'lucide-react'
import { AddOutfitModal } from '@/components/AddOutfitModal'
import Link from 'next/link'
import { usePathname } from 'next/navigation'
import { client } from '@/lib/client'
import { ThemeToggle } from '@/components/ui/theme-toggle'

// Move static data outside component
const GREETING_HOURS = {
MORNING: 12,
AFTERNOON: 18
Expand Down Expand Up @@ -48,16 +45,28 @@ export default function AuthenticatedHeader() {
<p className="text-base text-muted-foreground">{today}</p>
</div>
<div className="transition-colors duration-300">
<ThemeToggle />
<Link href="/settings">
<Button
variant="outline"
size="icon"
aria-label="Settings"
className="rounded-full w-9 h-9 bg-transparent hover:bg-muted/50 border-border"
>
<Settings className="h-[1.2rem] w-[1.2rem]" />
<span className="sr-only">Settings</span>
</Button>
</Link>
</div>
</header>
<nav className="mb-6 sm:mb-8 fade-in flex flex-col sm:flex-row gap-3 sm:gap-0 justify-between items-stretch sm:items-center">
<div className="flex flex-col sm:flex-row gap-3">
{NAV_LINKS.map(({ href, label, Icon }) => (
<Link key={href} href={href} className="w-full sm:w-auto">
<Button
variant={pathname === href ? "default" : "secondary"}
className="w-full sm:w-auto"
variant="outline"
className={`w-full sm:w-auto bg-transparent hover:bg-muted/50 border-border transition-colors ${
pathname === href ? "bg-muted/30 text-foreground" : "text-muted-foreground"
}`}
>
<Icon className="mr-1 h-4 w-4 sm:h-5 sm:w-5" />
{label}
Expand Down
2 changes: 2 additions & 0 deletions next/src/components/OutfitSuggestions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ export default function OutfitSuggestions() {
hexColor={tag.hexColor}
selected={selectedTagId === tag.id}
onClick={() => handleTagClick(tag.id)}
compact={false}
/>
))
) : (
Expand Down Expand Up @@ -119,6 +120,7 @@ export default function OutfitSuggestions() {
name={tag.name}
hexColor={tag.hexColor}
selected={true}
compact={true}
/>
)
})}
Expand Down
Loading
Loading