11"use client" ;
22
3+ import { Button } from "@/components/ui/button" ;
4+ import { Input } from "@/components/ui/input" ;
5+ import { ArrowRight01Icon , Building03Icon , Plus , PlusSignIcon } from "@hugeicons/core-free-icons" ;
6+ import { HugeiconsIcon } from "@hugeicons/react" ;
37import { PageHeader } from "@/components/ui/page-header" ;
48
59export default function WorkspaceSettingsPage ( ) {
@@ -11,6 +15,158 @@ export default function WorkspaceSettingsPage() {
1115 icon = { Building03Icon }
1216 />
1317
18+ < div className = "flex-1 max-w-4xl grid grid-cols-1 md:grid-cols-12 gap-8 items-start" >
19+
20+ { /* Workspaces List */ }
21+ < div className = "md:col-span-7 space-y-6" >
22+ < div className = "bg-card/50 backdrop-blur-xl ring-1 ring-border/75 shadow-lg rounded-2xl overflow-hidden transition-all duration-300" >
23+ < div className = "p-6 border-b border-border/50 bg-muted/20" >
24+ < h2 className = "text-lg font-semibold tracking-tight text-foreground flex items-center gap-2" >
25+ < HugeiconsIcon icon = { Building03Icon } className = "w-5 h-5 text-primary" />
26+ Active Workspaces
27+ </ h2 >
28+ < p className = "text-sm text-muted-foreground mt-1" > Select a workspace to switch contexts.</ p >
29+ </ div >
30+ < div className = "p-6" >
31+ { isLoading ? (
32+ < div className = "flex items-center justify-center py-8 text-muted-foreground animate-pulse" >
33+ Loading workspaces...
34+ </ div >
35+ ) : ! organization ? (
36+ < div className = "flex flex-col items-center justify-center py-12 text-center text-destructive" >
37+ < div className = "bg-destructive/10 p-4 rounded-full mb-4" >
38+ < HugeiconsIcon icon = { Building03Icon } className = "w-6 h-6 text-destructive" />
39+ </ div >
40+ < p className = "font-medium" > Failed to load organization.</ p >
41+ < p className = "text-sm opacity-80 mt-1" > Please try refreshing the page.</ p >
42+ </ div >
43+ ) : workspaces . length === 0 ? (
44+ < div className = "flex flex-col items-center justify-center py-12 text-center text-muted-foreground" >
45+ < div className = "bg-muted p-4 rounded-full mb-4" >
46+ < HugeiconsIcon icon = { Building03Icon } className = "w-6 h-6 opacity-50" />
47+ </ div >
48+ < p > No workspaces found.</ p >
49+ </ div >
50+ ) : (
51+ < ul className = "space-y-3" >
52+ { workspaces . map ( ( ws ) => {
53+ const isActive = activeWorkspaceId === ws . id ;
54+ return (
55+ < li
56+ key = { ws . id }
57+ className = { `group flex items-center justify-between p-4 rounded-xl transition-all duration-300 ring-1 ${
58+ isActive
59+ ? "bg-primary/5 ring-primary/20 shadow-sm ring-1"
60+ : "bg-background ring-border/75 hover:border-primary/30 hover:shadow-md hover:-translate-y-0.5 cursor-pointer"
61+ } `}
62+ onClick = { ( ) => ! isActive && setActiveWorkspaceId ( ws . id ) }
63+ >
64+ < div className = "flex items-center gap-4" >
65+ < div >
66+ < div className = "font-semibold text-foreground" > { ws . name } </ div >
67+ { isMultiOrg && (
68+ < div className = "text-xs text-muted-foreground mt-0.5" >
69+ { ws . org_name }
70+ </ div >
71+ ) }
72+ </ div >
73+ </ div >
74+ { isActive ? (
75+ < div className = "px-3 py-1 bg-primary text-primary-foreground text-xs font-medium rounded-full shadow-sm" >
76+ Active
77+ </ div >
78+ ) : (
79+ < Button variant = "ghost" size = "sm" className = "opacity-0 group-hover:opacity-100 transition-opacity -mr-2" >
80+ Switch < HugeiconsIcon icon = { ArrowRight01Icon } className = "w-4 h-4 ml-1" />
81+ </ Button >
82+ ) }
83+ </ li >
84+ ) ;
85+ } ) }
86+ </ ul >
87+ ) }
88+ </ div >
89+ </ div >
90+ </ div >
91+
92+ { /* Create Workspace */ }
93+ < div className = "md:col-span-5 flex flex-col" >
94+ < div className = "flex-1 bg-linear-to-br from-card to-card/50 backdrop-blur-xl ring ring-border/75 shadow-lg rounded-2xl p-6 relative overflow-hidden" >
95+ { /* Decorative background accent */ }
96+ < div className = "absolute top-0 right-0 -mr-8 -mt-8 w-32 h-32 bg-primary/10 rounded-full blur-3xl pointer-events-none" > </ div >
97+
98+ < div className = "mb-6 relative z-10" >
99+ < div className = "inline-flex items-center justify-center w-10 h-10 rounded-lg bg-primary/10 text-primary mb-4" >
100+ < HugeiconsIcon icon = { Plus } className = "w-5 h-5" />
101+ </ div >
102+ < h2 className = "text-lg font-semibold tracking-tight text-foreground" > Create New Workspace</ h2 >
103+ < p className = "text-sm text-muted-foreground mt-1" >
104+ Spin up a new environment for a different project, team, or client.
105+ </ p >
106+ </ div >
107+
108+ < form onSubmit = { handleCreate } className = "space-y-4 relative z-10" >
109+ { isMultiOrg && (
110+ < div className = "space-y-1.5" >
111+ < label className = "text-sm font-medium text-foreground" > Organization</ label >
112+ < div className = "flex flex-wrap gap-2" >
113+ { Array . from ( new Set ( workspaces . map ( w => w . org_id ) ) ) . map ( orgId => {
114+ const orgName = workspaces . find ( w => w . org_id === orgId ) ?. org_name || orgId ;
115+ return (
116+ < button
117+ key = { orgId }
118+ type = "button"
119+ onClick = { ( ) => setSelectedOrgId ( orgId ) }
120+ className = { `px-3 py-1 rounded-full text-xs border transition-colors ${
121+ ( selectedOrgId || organization ?. id ) === orgId
122+ ? "bg-primary text-primary-foreground border-primary"
123+ : "bg-transparent text-muted-foreground border-border hover:border-foreground/40"
124+ } `}
125+ >
126+ { orgName }
127+ </ button >
128+ ) ;
129+ } ) }
130+ </ div >
131+ </ div >
132+ ) }
133+ < div className = "space-y-2" >
134+ < label className = "text-sm font-medium text-foreground" > Workspace Name</ label >
135+ < Input
136+ value = { newWorkspaceName }
137+ onChange = { ( e ) => setNewWorkspaceName ( e . target . value ) }
138+ placeholder = "e.g. Acme Corp Production"
139+ className = "bg-background/50 border-border/50 focus-visible:ring-primary/50 transition-all h-11"
140+ disabled = { isCreating }
141+ />
142+ </ div >
143+ < Button
144+ type = "submit"
145+ className = "w-full h-11 font-medium shadow-md transition-all hover:shadow-lg active:scale-[0.98]"
146+ disabled = { isCreating || ! newWorkspaceName . trim ( ) || ! organization }
147+ >
148+ { isCreating ? (
149+ < span className = "flex items-center" >
150+ < svg className = "animate-spin -ml-1 mr-3 h-5 w-5 text-white" xmlns = "http://www.w3.org/2000/svg" fill = "none" viewBox = "0 0 24 24" >
151+ < circle className = "opacity-25" cx = "12" cy = "12" r = "10" stroke = "currentColor" strokeWidth = "4" > </ circle >
152+ < path className = "opacity-75" fill = "currentColor" d = "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z" > </ path >
153+ </ svg >
154+ Creating...
155+ </ span >
156+ ) : (
157+ < span className = "flex items-center" >
158+ < HugeiconsIcon icon = { PlusSignIcon } className = "w-5 h-5 mr-2" />
159+ Create Workspace
160+ </ span >
161+ ) }
162+ </ Button >
163+ </ form >
164+ </ div >
165+ </ div >
166+
167+ </ div >
168+ { /* END-INTERNAL */ }
169+
14170 < div className = "hidden in-[.open-source]:block text-sm text-muted-foreground" >
15171 Workspace management is not available in the open source version.
16172 </ div >
0 commit comments