Skip to content

Commit 40c0d0b

Browse files
committed
some empty states cleaned up, ui cleanups, and more
1 parent 88d5928 commit 40c0d0b

File tree

21 files changed

+231
-869
lines changed

21 files changed

+231
-869
lines changed

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

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -159,24 +159,24 @@ export function OrganizationLogoUploader({
159159

160160
return (
161161
<div className="space-y-3">
162-
<div className="flex items-center gap-3">
162+
<div className="mt-5 flex items-center gap-3">
163163
<div className="group relative">
164-
<Avatar className="h-16 w-16 border border-border/30 shadow-sm">
164+
<Avatar className="size-10 border">
165165
<AvatarImage alt={organization.name} src={preview || undefined} />
166166
<AvatarFallback className="bg-accent font-medium text-sm">
167167
{getOrganizationInitials(organization.name)}
168168
</AvatarFallback>
169169
</Avatar>
170170
<button
171171
aria-label="Upload new organization logo"
172-
className="absolute inset-0 flex cursor-pointer items-center justify-center rounded-full bg-black/50 opacity-0 transition-opacity group-hover:opacity-100"
172+
className="absolute inset-0 flex cursor-pointer items-center justify-center rounded-full bg-foreground opacity-0 transition-opacity group-hover:opacity-100"
173173
onClick={() => fileInputRef.current?.click()}
174174
type="button"
175175
>
176-
<UploadSimpleIcon className="text-white" size={20} />
176+
<UploadSimpleIcon className="text-accent" size={20} />
177177
</button>
178178
</div>
179-
<div className="space-y-2">
179+
<div className="space-y-1">
180180
<p className="font-medium text-foreground text-sm">
181181
Update your logo
182182
</p>

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

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ export function OrganizationsList({
122122
className={cn(
123123
"group relative cursor-pointer overflow-hidden transition-all duration-200",
124124
isActive
125-
? "cursor-default bg-sidebar-accent"
125+
? "cursor-default"
126126
: isProcessing && "pointer-events-none opacity-70"
127127
)}
128128
key={org.id}
@@ -147,12 +147,7 @@ export function OrganizationsList({
147147
<div className="flex flex-col items-start gap-3 space-y-3 md:flex-row">
148148
<Avatar className="size-9 shrink-0">
149149
<AvatarImage alt={org.name} src={org.logo || undefined} />
150-
<AvatarFallback
151-
className={cn(
152-
"font-medium text-xs",
153-
isActive ? "bg-secondary-brightest" : "bg-accent"
154-
)}
155-
>
150+
<AvatarFallback className="bg-secondary font-medium text-xs">
156151
{getOrganizationInitials(org.name)}
157152
</AvatarFallback>
158153
</Avatar>

apps/dashboard/app/(main)/organizations/invitations/invitation-list.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,10 @@ import type { CancelInvitation, Invitation } from "@/hooks/use-organizations";
1919

2020
dayjs.extend(relativeTime);
2121

22-
interface InvitationToCancel {
22+
type InvitationToCancel = {
2323
id: string;
2424
email: string;
25-
}
25+
};
2626

2727
export function InvitationList({
2828
invitations,

apps/dashboard/app/(main)/organizations/invitations/invitations-view.tsx

Lines changed: 49 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,26 +6,38 @@ import {
66
EnvelopeIcon,
77
XIcon,
88
} from "@phosphor-icons/react";
9+
import { useState } from "react";
10+
import { EmptyState } from "@/components/empty-state";
11+
import { InviteMemberDialog } from "@/components/organizations/invite-member-dialog";
912
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
1013
import { useOrganizationInvitations } from "@/hooks/use-organization-invitations";
1114
import type {
1215
ActiveOrganization,
1316
Organization,
1417
} from "@/hooks/use-organizations";
15-
import { EmptyState } from "../components/empty-state";
1618
import { ListSkeleton } from "../components/list-skeleton";
1719
import { InvitationList } from "./invitation-list";
1820

1921
function InvitationsSkeleton() {
2022
return <ListSkeleton count={6} />;
2123
}
2224

23-
function EmptyInvitationsState() {
25+
function EmptyInvitationsState({
26+
setShowInviteMemberDialog,
27+
}: {
28+
setShowInviteMemberDialog: () => void;
29+
}) {
2430
return (
2531
<EmptyState
32+
action={{
33+
label: "Invite Member",
34+
onClick: setShowInviteMemberDialog,
35+
size: "sm",
36+
}}
2637
description="There are no pending invitations for this organization. All invited members have either joined or declined their invitations."
27-
icon={EnvelopeIcon}
38+
icon={<EnvelopeIcon weight="duotone" />}
2839
title="No Pending Invitations"
40+
variant="minimal"
2941
/>
3042
);
3143
}
@@ -47,6 +59,8 @@ export function InvitationsView({
4759
setTab,
4860
} = useOrganizationInvitations(organization.id);
4961

62+
const [showInviteMemberDialog, setShowInviteMemberDialog] = useState(false);
63+
5064
if (isLoadingInvitations) {
5165
return <InvitationsSkeleton />;
5266
}
@@ -55,7 +69,18 @@ export function InvitationsView({
5569
!filteredInvitations ||
5670
(pendingCount === 0 && expiredCount === 0 && acceptedCount === 0)
5771
) {
58-
return <EmptyInvitationsState />;
72+
return (
73+
<div className="flex h-full flex-col">
74+
<InviteMemberDialog
75+
onOpenChange={setShowInviteMemberDialog}
76+
open={showInviteMemberDialog}
77+
organizationId={organization.id}
78+
/>
79+
<EmptyInvitationsState
80+
setShowInviteMemberDialog={() => setShowInviteMemberDialog(true)}
81+
/>
82+
</div>
83+
);
5984
}
6085

6186
return (
@@ -129,7 +154,12 @@ export function InvitationsView({
129154
) : (
130155
<EmptyState
131156
description="All sent invitations have been responded to or have expired."
132-
icon={EnvelopeIcon}
157+
icon={
158+
<EnvelopeIcon
159+
className="size-6 text-accent-foreground"
160+
weight="duotone"
161+
/>
162+
}
133163
title="No Pending Invitations"
134164
/>
135165
)}
@@ -145,9 +175,14 @@ export function InvitationsView({
145175
) : (
146176
<EmptyState
147177
description="Great! You don't have any expired invitations at the moment."
148-
icon={ClockIcon}
178+
icon={
179+
<ClockIcon
180+
className="size-6 text-accent-foreground"
181+
weight="duotone"
182+
/>
183+
}
149184
title="No Expired Invitations"
150-
variant="warning"
185+
variant="minimal"
151186
/>
152187
)}
153188
</TabsContent>
@@ -162,9 +197,14 @@ export function InvitationsView({
162197
) : (
163198
<EmptyState
164199
description="When team members accept invitations, they'll appear here."
165-
icon={CheckIcon}
200+
icon={
201+
<CheckIcon
202+
className="size-6 text-accent-foreground"
203+
weight="duotone"
204+
/>
205+
}
166206
title="No Accepted Invitations Yet"
167-
variant="success"
207+
variant="minimal"
168208
/>
169209
)}
170210
</TabsContent>

apps/dashboard/app/(main)/organizations/settings/danger/danger-zone-settings.tsx

Lines changed: 46 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ export function DangerZoneSettings({
9292
<div className="space-y-8">
9393
{/* Transfer Assets Section */}
9494
<div className="rounded-lg border bg-card">
95-
<div className="border-b p-6">
95+
<div className="border-b p-5">
9696
<h3 className="font-semibold text-lg">Transfer Assets</h3>
9797
<p className="text-muted-foreground text-sm">
9898
Move websites between your personal account and organization
@@ -104,52 +104,50 @@ export function DangerZoneSettings({
104104
</div>
105105

106106
{/* Leave/Delete Organization Section */}
107-
<div className="rounded-lg border border-destructive/20 bg-destructive/5">
108-
<div className="p-6">
109-
<div className="space-y-4">
110-
<div>
111-
<h3 className="font-semibold text-destructive text-lg">
112-
{isOwner === null
113-
? "Loading..."
114-
: isOwner
115-
? "Delete Organization"
116-
: "Leave Organization"}
117-
</h3>
118-
<p className="text-destructive/80 text-sm">
119-
{isOwner === null
120-
? "Checking permissions..."
121-
: isOwner
122-
? "Once you delete an organization, there is no going back. Please be certain."
123-
: "You will lose access to this organization and all its resources."}
124-
</p>
125-
</div>
107+
<div className="rounded-lg border border-destructive/20 bg-destructive/10 p-4">
108+
<div className="flex flex-wrap items-center justify-between space-y-4">
109+
<div>
110+
<h3 className="font-semibold text-destructive text-lg">
111+
{isOwner === null
112+
? "Loading..."
113+
: isOwner
114+
? "Delete Organization"
115+
: "Leave Organization"}
116+
</h3>
117+
<p className="text-destructive/80 text-sm">
118+
{isOwner === null
119+
? "Checking permissions..."
120+
: isOwner
121+
? "Once you delete an organization, there is no going back. Please be certain."
122+
: "You will lose access to this organization and all its resources."}
123+
</p>
124+
</div>
126125

127-
<div className="flex justify-end">
128-
{isOwner === null ? (
129-
<Button disabled size="default" variant="destructive">
130-
<div className="mr-2 h-4 w-4 animate-spin rounded-full border border-destructive-foreground/30 border-t-destructive-foreground" />
131-
Loading...
132-
</Button>
133-
) : isOwner ? (
134-
<Button
135-
onClick={() => setShowDeleteDialog(true)}
136-
size="default"
137-
variant="destructive"
138-
>
139-
<TrashIcon className="mr-2 h-4 w-4" size={16} />
140-
Delete Organization
141-
</Button>
142-
) : (
143-
<Button
144-
onClick={() => setShowLeaveDialog(true)}
145-
size="default"
146-
variant="destructive"
147-
>
148-
<SignOutIcon className="mr-2 h-4 w-4" size={16} />
149-
Leave Organization
150-
</Button>
151-
)}
152-
</div>
126+
<div className="flex">
127+
{isOwner === null ? (
128+
<Button disabled size="default" variant="destructive">
129+
<div className="mr-1 size-4 animate-spin rounded-full border border-destructive-foreground/30 border-t-destructive-foreground" />
130+
Loading...
131+
</Button>
132+
) : isOwner ? (
133+
<Button
134+
onClick={() => setShowDeleteDialog(true)}
135+
size="default"
136+
variant="destructive"
137+
>
138+
<TrashIcon className="size-4" size={16} />
139+
Delete Organization
140+
</Button>
141+
) : (
142+
<Button
143+
onClick={() => setShowLeaveDialog(true)}
144+
size="default"
145+
variant="destructive"
146+
>
147+
<SignOutIcon className="mr-2 h-4 w-4" size={16} />
148+
Leave Organization
149+
</Button>
150+
)}
153151
</div>
154152
</div>
155153
</div>
@@ -168,18 +166,11 @@ export function DangerZoneSettings({
168166
<AlertDialogFooter>
169167
<AlertDialogCancel>Cancel</AlertDialogCancel>
170168
<AlertDialogAction
171-
className="bg-destructive text-destructive-foreground hover:bg-destructive/90"
169+
className="bg-destructive text-red-700"
172170
disabled={isDeleting}
173171
onClick={handleDelete}
174172
>
175-
{isDeleting ? (
176-
<>
177-
<div className="mr-2 h-4 w-4 animate-spin rounded-full border border-destructive-foreground/30 border-t-destructive-foreground" />
178-
Deleting...
179-
</>
180-
) : (
181-
"Delete Organization"
182-
)}
173+
{isDeleting ? "Deleting..." : "Delete Organization"}
183174
</AlertDialogAction>
184175
</AlertDialogFooter>
185176
</AlertDialogContent>

0 commit comments

Comments
 (0)