Skip to content

Commit 7146a6a

Browse files
committed
refactor and clean up orgs
1 parent 40c8b9f commit 7146a6a

File tree

11 files changed

+347
-317
lines changed

11 files changed

+347
-317
lines changed
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
'use client';
2+
3+
import { type Icon } from '@phosphor-icons/react';
4+
import { type ReactNode } from 'react';
5+
6+
interface EmptyStateProps {
7+
icon: Icon;
8+
title: string;
9+
description: string;
10+
features?: Array<{
11+
label: string;
12+
}>;
13+
action?: ReactNode;
14+
variant?: 'default' | 'success' | 'warning' | 'destructive';
15+
}
16+
17+
export function EmptyState({
18+
icon: Icon,
19+
title,
20+
description,
21+
features,
22+
action,
23+
variant = 'default',
24+
}: EmptyStateProps) {
25+
const variantStyles = {
26+
default: 'border-primary/20 bg-primary/10 text-primary',
27+
success: 'border-green-200 bg-green-100 text-green-600',
28+
warning: 'border-orange-200 bg-orange-100 text-orange-600',
29+
destructive: 'border-destructive/20 bg-destructive/10 text-destructive',
30+
};
31+
32+
return (
33+
<div className="flex h-full flex-col items-center justify-center p-4 text-center sm:p-8">
34+
<div className={`mx-auto mb-6 w-fit rounded-2xl border p-6 sm:mb-8 sm:p-8 ${variantStyles[variant]}`}>
35+
<Icon
36+
className="h-12 w-12 sm:h-16 sm:w-16"
37+
size={48}
38+
weight="duotone"
39+
/>
40+
</div>
41+
<h3 className="mb-3 font-bold text-xl sm:mb-4 sm:text-2xl">{title}</h3>
42+
<p className="mb-6 max-w-md text-muted-foreground text-sm leading-relaxed sm:mb-8 sm:text-base">
43+
{description}
44+
</p>
45+
{features && (
46+
<div className="rounded-lg border border-dashed bg-muted/20 p-4 sm:p-6">
47+
<div className="flex flex-col items-center justify-center gap-2 text-muted-foreground text-xs sm:flex-row sm:gap-3 sm:text-sm">
48+
{features.map((feature, index) => (
49+
<div key={index} className="flex items-center gap-2">
50+
<div className="h-2 w-2 rounded-full bg-primary" />
51+
<span>{feature.label}</span>
52+
</div>
53+
))}
54+
</div>
55+
</div>
56+
)}
57+
{action && <div className="mt-4 sm:mt-6">{action}</div>}
58+
</div>
59+
);
60+
}

apps/dashboard/app/(main)/organizations/components/general-settings.tsx

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -63,16 +63,16 @@ export function GeneralSettings({ organization }: GeneralSettingsProps) {
6363
const hasChanges = name !== organization.name || slug !== organization.slug;
6464

6565
return (
66-
<div className="h-full p-6">
67-
<div className="space-y-8">
66+
<div className="h-full p-4 sm:p-6">
67+
<div className="space-y-6 sm:space-y-8">
6868
{/* Content Sections */}
69-
<div className="space-y-8">
69+
<div className="space-y-6 sm:space-y-8">
7070
{/* Logo Upload Section */}
71-
<div className="rounded border bg-card p-6">
72-
<div className="space-y-4">
71+
<div className="rounded border bg-card p-4 sm:p-6">
72+
<div className="space-y-3 sm:space-y-4">
7373
<div>
74-
<h3 className="font-semibold text-lg">Organization Logo</h3>
75-
<p className="text-muted-foreground text-sm">
74+
<h3 className="font-semibold text-base sm:text-lg">Organization Logo</h3>
75+
<p className="text-muted-foreground text-xs sm:text-sm">
7676
Upload a logo to represent your organization
7777
</p>
7878
</div>
@@ -81,18 +81,18 @@ export function GeneralSettings({ organization }: GeneralSettingsProps) {
8181
</div>
8282

8383
{/* Name and Slug Section */}
84-
<div className="rounded border bg-card p-6">
85-
<div className="space-y-6">
84+
<div className="rounded border bg-card p-4 sm:p-6">
85+
<div className="space-y-4 sm:space-y-6">
8686
<div>
87-
<h3 className="font-semibold text-lg">Basic Information</h3>
88-
<p className="text-muted-foreground text-sm">
87+
<h3 className="font-semibold text-base sm:text-lg">Basic Information</h3>
88+
<p className="text-muted-foreground text-xs sm:text-sm">
8989
Configure your organization's name and URL identifier
9090
</p>
9191
</div>
9292

93-
<div className="grid gap-6 sm:grid-cols-2">
94-
<div className="space-y-3">
95-
<Label className="font-medium" htmlFor="name">
93+
<div className="grid gap-4 sm:gap-6 sm:grid-cols-2">
94+
<div className="space-y-2 sm:space-y-3">
95+
<Label className="font-medium text-xs sm:text-sm" htmlFor="name">
9696
Organization Name
9797
</Label>
9898
<Input
@@ -102,8 +102,8 @@ export function GeneralSettings({ organization }: GeneralSettingsProps) {
102102
value={name}
103103
/>
104104
</div>
105-
<div className="space-y-3">
106-
<Label className="font-medium" htmlFor="slug">
105+
<div className="space-y-2 sm:space-y-3">
106+
<Label className="font-medium text-xs sm:text-sm" htmlFor="slug">
107107
Organization Slug
108108
</Label>
109109
<Input
@@ -120,20 +120,20 @@ export function GeneralSettings({ organization }: GeneralSettingsProps) {
120120

121121
{/* Save Button */}
122122
{hasChanges && (
123-
<div className="flex justify-end border-t pt-4">
123+
<div className="flex justify-end border-t pt-3 sm:pt-4">
124124
<Button
125-
className="px-6"
125+
className="px-4 text-xs sm:px-6 sm:text-sm"
126126
disabled={isSaving}
127127
onClick={handleSave}
128128
>
129129
{isSaving ? (
130130
<>
131-
<div className="mr-2 h-4 w-4 animate-spin rounded-full border border-primary-foreground/30 border-t-primary-foreground" />
131+
<div className="mr-2 h-3 w-3 animate-spin rounded-full border border-primary-foreground/30 border-t-primary-foreground sm:h-4 sm:w-4" />
132132
Saving...
133133
</>
134134
) : (
135135
<>
136-
<FloppyDiskIcon className="mr-2 h-4 w-4" size={16} />
136+
<FloppyDiskIcon className="mr-2 h-3 w-3 sm:h-4 sm:w-4" size={12} />
137137
Save Changes
138138
</>
139139
)}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
'use client';
2+
3+
import { Skeleton } from '@/components/ui/skeleton';
4+
5+
interface ListSkeletonProps {
6+
count?: number;
7+
showAvatar?: boolean;
8+
showActions?: boolean;
9+
}
10+
11+
export function ListSkeleton({ count = 6, showAvatar = true, showActions = true }: ListSkeletonProps) {
12+
return (
13+
<div className="h-full p-4 sm:p-6">
14+
<div className="space-y-3 sm:space-y-4">
15+
{Array.from({ length: count }).map((_, i) => (
16+
<div
17+
className="flex items-center gap-3 rounded-lg border bg-card p-3 sm:gap-4 sm:p-4"
18+
key={i.toString()}
19+
>
20+
{showAvatar && (
21+
<Skeleton className="h-10 w-10 flex-shrink-0 rounded-full sm:h-12 sm:w-12" />
22+
)}
23+
<div className="min-w-0 flex-1 space-y-2">
24+
<Skeleton className="h-3 w-40 sm:h-4 sm:w-48" />
25+
<Skeleton className="h-3 w-32 sm:h-3 sm:w-40" />
26+
</div>
27+
{showActions && (
28+
<Skeleton className="h-7 w-16 sm:h-8 sm:w-20" />
29+
)}
30+
</div>
31+
))}
32+
</div>
33+
</div>
34+
);
35+
}

apps/dashboard/app/(main)/organizations/components/organization-provider.tsx

Lines changed: 53 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -127,22 +127,22 @@ export function OrganizationProvider({
127127
<div className="border-b bg-gradient-to-r from-background via-background to-muted/20">
128128
<div className="flex flex-col justify-between gap-3 p-4 sm:flex-row sm:items-center sm:gap-0 sm:px-6 sm:py-6">
129129
<div className="min-w-0 flex-1">
130-
<div className="flex items-center gap-4">
131-
<div className="rounded border border-primary/20 bg-primary/10 p-3">
132-
<Skeleton className="h-6 w-6" />
130+
<div className="flex items-center gap-3 sm:gap-4">
131+
<div className="rounded border border-primary/20 bg-primary/10 p-2 sm:p-3">
132+
<Skeleton className="h-5 w-5 sm:h-6 sm:w-6" />
133133
</div>
134134
<div>
135-
<Skeleton className="h-8 w-48" />
136-
<Skeleton className="mt-1 h-4 w-64" />
135+
<Skeleton className="h-6 w-32 sm:h-8 sm:w-48" />
136+
<Skeleton className="mt-1 h-3 w-48 sm:h-4 sm:w-64" />
137137
</div>
138138
</div>
139139
</div>
140140
</div>
141141
</div>
142142
<main className="flex-1 overflow-y-auto p-4 sm:p-6">
143-
<Skeleton className="h-48 w-full" />
144-
<Skeleton className="h-32 w-full" />
145-
<Skeleton className="h-24 w-full" />
143+
<Skeleton className="h-32 w-full sm:h-48" />
144+
<Skeleton className="h-24 w-full sm:h-32" />
145+
<Skeleton className="h-20 w-full sm:h-24" />
146146
</main>
147147
</div>
148148
);
@@ -154,57 +154,57 @@ export function OrganizationProvider({
154154
<div className="border-b bg-gradient-to-r from-background via-background to-muted/20">
155155
<div className="flex flex-col justify-between gap-3 p-4 sm:flex-row sm:items-center sm:gap-0 sm:px-6 sm:py-6">
156156
<div className="min-w-0 flex-1">
157-
<div className="flex items-center gap-4">
158-
<div className="rounded border border-primary/20 bg-primary/10 p-3">
157+
<div className="flex items-center gap-3 sm:gap-4">
158+
<div className="rounded border border-primary/20 bg-primary/10 p-2 sm:p-3">
159159
<Icon
160-
className="h-6 w-6 text-primary"
161-
size={24}
160+
className="h-5 w-5 text-primary sm:h-6 sm:w-6"
161+
size={20}
162162
weight="duotone"
163163
/>
164164
</div>
165165
<div>
166-
<h1 className="truncate font-bold text-2xl text-foreground tracking-tight sm:text-3xl">
166+
<h1 className="truncate font-bold text-xl text-foreground tracking-tight sm:text-2xl lg:text-3xl">
167167
{title}
168168
</h1>
169-
<p className="mt-1 text-muted-foreground text-sm sm:text-base">
169+
<p className="mt-1 text-muted-foreground text-xs sm:text-sm lg:text-base">
170170
{description}
171171
</p>
172172
</div>
173173
</div>
174174
</div>
175175
{actionButton && (
176176
<Button
177-
className="w-full rounded sm:w-auto"
177+
className="w-full rounded text-xs sm:w-auto sm:text-sm"
178178
onClick={actionButton.action}
179179
size="sm"
180180
>
181-
<actionButton.icon className="mr-2 h-4 w-4" size={16} />
181+
<actionButton.icon className="mr-2 h-3 w-3 sm:h-4 sm:w-4" size={12} />
182182
{actionButton.text}
183183
</Button>
184184
)}
185185
</div>
186186
</div>
187187

188-
<main className="flex flex-1 items-center justify-center p-6">
189-
<div className="w-full max-w-md rounded-lg border bg-card p-8 text-center">
188+
<main className="flex flex-1 items-center justify-center p-4 sm:p-6">
189+
<div className="w-full max-w-md rounded-lg border bg-card p-6 text-center sm:p-8">
190190
<Icon
191-
className="mx-auto mb-4 h-12 w-12 text-muted-foreground"
192-
size={48}
191+
className="mx-auto mb-3 h-10 w-10 text-muted-foreground sm:mb-4 sm:h-12 sm:w-12"
192+
size={40}
193193
weight="duotone"
194194
/>
195-
<h3 className="mb-2 font-semibold text-lg">
195+
<h3 className="mb-2 font-semibold text-base sm:text-lg">
196196
Select an Organization
197197
</h3>
198-
<p className="text-muted-foreground text-sm">
198+
<p className="text-muted-foreground text-xs sm:text-sm">
199199
This feature requires an active organization.
200200
</p>
201-
<div className="mt-6">
201+
<div className="mt-4 sm:mt-6">
202202
<Button
203-
className="rounded"
203+
className="rounded text-xs sm:text-sm"
204204
onClick={() => setShowCreateDialog(true)}
205205
size="default"
206206
>
207-
<BuildingsIcon className="mr-2 h-5 w-5" size={20} />
207+
<BuildingsIcon className="mr-2 h-4 w-4 sm:h-5 sm:w-5" size={16} />
208208
Create organization
209209
</Button>
210210
</div>
@@ -217,36 +217,36 @@ export function OrganizationProvider({
217217
return (
218218
<div className="flex h-full flex-col">
219219
<div className="border-b bg-gradient-to-r from-background via-background to-muted/20">
220-
<div className="flex flex-col justify-between gap-3 p-4 sm:flex-row sm:items-center sm:gap-0 sm:px-6 sm:py-6">
221-
<div className="min-w-0 flex-1">
222-
<div className="flex items-center gap-4">
223-
<div className="rounded border border-primary/20 bg-primary/10 p-3">
224-
<Icon
225-
className="h-6 w-6 text-primary"
226-
size={24}
227-
weight="duotone"
228-
/>
229-
</div>
230-
<div>
231-
<h1 className="truncate font-bold text-2xl text-foreground tracking-tight sm:text-3xl">
232-
{title}
233-
</h1>
234-
<p className="mt-1 text-muted-foreground text-sm sm:text-base">
235-
{description}
236-
</p>
220+
<div className="flex flex-col justify-between gap-3 p-4 sm:flex-row sm:items-center sm:gap-0 sm:px-6 sm:py-6">
221+
<div className="min-w-0 flex-1">
222+
<div className="flex items-center gap-3 sm:gap-4">
223+
<div className="rounded border border-primary/20 bg-primary/10 p-2 sm:p-3">
224+
<Icon
225+
className="h-5 w-5 text-primary sm:h-6 sm:w-6"
226+
size={20}
227+
weight="duotone"
228+
/>
229+
</div>
230+
<div>
231+
<h1 className="truncate font-bold text-xl text-foreground tracking-tight sm:text-2xl lg:text-3xl">
232+
{title}
233+
</h1>
234+
<p className="mt-1 text-muted-foreground text-xs sm:text-sm lg:text-base">
235+
{description}
236+
</p>
237+
</div>
237238
</div>
238239
</div>
239-
</div>
240-
{actionButton && (
241-
<Button
242-
className="w-full rounded sm:w-auto"
243-
onClick={actionButton.action}
244-
size="sm"
245-
>
246-
<actionButton.icon className="mr-2 h-4 w-4" size={16} />
247-
{actionButton.text}
248-
</Button>
249-
)}
240+
{actionButton && (
241+
<Button
242+
className="w-full rounded text-xs sm:w-auto sm:text-sm"
243+
onClick={actionButton.action}
244+
size="sm"
245+
>
246+
<actionButton.icon className="mr-2 h-3 w-3 sm:h-4 sm:w-4" size={12} />
247+
{actionButton.text}
248+
</Button>
249+
)}
250250
</div>
251251
</div>
252252

0 commit comments

Comments
 (0)