Skip to content

Commit 0cafb0c

Browse files
committed
fix: adding websites optimistically
1 parent 01e8116 commit 0cafb0c

File tree

4 files changed

+43
-92
lines changed

4 files changed

+43
-92
lines changed

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

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,10 @@
22

33
import {
44
ArrowRightIcon,
5-
BuildingsIcon,
65
CalendarIcon,
76
CheckIcon,
87
GearIcon,
9-
PlusIcon,
108
TrashIcon,
11-
UsersIcon,
129
} from '@phosphor-icons/react';
1310
import dayjs from 'dayjs';
1411
import relativeTime from 'dayjs/plugin/relativeTime';
@@ -29,7 +26,7 @@ import {
2926
import {
3027
type ActiveOrganization,
3128
type Organization,
32-
useOrganizations,
29+
useOrganizations,
3330
} from '@/hooks/use-organizations';
3431
import { cn, getOrganizationInitials } from '@/lib/utils';
3532
import { OnboardingCard } from './onboarding-card';

apps/dashboard/app/(main)/websites/page.tsx

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -170,10 +170,6 @@ export default function WebsitesPage() {
170170
refetch();
171171
};
172172

173-
const handleWebsiteCreated = () => {
174-
refetch();
175-
};
176-
177173
return (
178174
<div className="flex h-full flex-col">
179175
{/* Enhanced header */}
@@ -283,7 +279,6 @@ export default function WebsitesPage() {
283279
{/* Website Dialog */}
284280
<WebsiteDialog
285281
onOpenChange={setDialogOpen}
286-
onSave={handleWebsiteCreated}
287282
open={dialogOpen}
288283
/>
289284
</div>

apps/dashboard/components/website-dialog.tsx

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ export function WebsiteDialog({
5252
open,
5353
onOpenChange,
5454
website,
55-
onSave = () => {},
55+
onSave,
5656
}: WebsiteDialogProps) {
5757
const isEditing = !!website;
5858
const { data: activeOrganization } = authClient.useActiveOrganization();
@@ -84,26 +84,26 @@ export function WebsiteDialog({
8484
organizationId: activeOrganization?.id,
8585
};
8686

87-
const promise = async () =>
88-
isEditing
89-
? updateWebsiteMutation.mutate({ id: website.id, name: formData.name })
90-
: createWebsiteMutation.mutate(submissionData);
91-
92-
toast.promise(promise(), {
93-
loading: 'Loading...',
94-
success: (result) => {
95-
onSave(result as unknown as Website);
96-
onOpenChange(false);
97-
return `Website ${isEditing ? 'updated' : 'created'} successfully!`;
98-
},
99-
error: (err: any) => {
100-
const message =
101-
err.data?.code === 'CONFLICT'
102-
? 'A website with this domain already exists.'
103-
: `Failed to ${isEditing ? 'update' : 'create'} website.`;
104-
return message;
105-
},
106-
});
87+
try {
88+
if (isEditing) {
89+
const result = await updateWebsiteMutation.mutateAsync({
90+
id: website.id,
91+
name: formData.name
92+
});
93+
if (onSave) onSave(result);
94+
toast.success('Website updated successfully!');
95+
} else {
96+
const result = await createWebsiteMutation.mutateAsync(submissionData);
97+
if (onSave) onSave(result);
98+
toast.success('Website created successfully!');
99+
}
100+
onOpenChange(false);
101+
} catch (error: any) {
102+
const message = error.data?.code === 'CONFLICT'
103+
? 'A website with this domain already exists.'
104+
: `Failed to ${isEditing ? 'update' : 'create'} website.`;
105+
toast.error(message);
106+
}
107107
});
108108

109109
return (

apps/dashboard/hooks/use-websites.ts

Lines changed: 21 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -36,78 +36,42 @@ export function useWebsite(id: string) {
3636
export function useCreateWebsite() {
3737
const utils = trpc.useUtils();
3838
return trpc.websites.create.useMutation({
39-
onMutate: async (newWebsite) => {
39+
onSuccess: (newWebsite, variables) => {
4040
const queryKey = {
41-
organizationId: newWebsite.organizationId ?? undefined,
41+
organizationId: variables.organizationId ?? undefined,
4242
};
43-
await utils.websites.list.cancel(queryKey);
44-
const previousWebsites = utils.websites.list.getData(queryKey);
45-
43+
4644
utils.websites.list.setData(queryKey, (old) => {
47-
const optimisticWebsite = {
48-
...newWebsite,
49-
id: crypto.randomUUID(),
50-
createdAt: new Date().toISOString(),
51-
} as Website;
52-
return old ? [...old, optimisticWebsite] : [optimisticWebsite];
45+
if (!old) return [newWebsite];
46+
const exists = old.some(w => w.id === newWebsite.id);
47+
return exists ? old : [...old, newWebsite];
5348
});
54-
55-
return { previousWebsites, queryKey };
56-
},
57-
onError: (_, __, context) => {
58-
if (context?.previousWebsites) {
59-
utils.websites.list.setData(context.queryKey, context.previousWebsites);
60-
}
6149
},
62-
onSettled: (_, __, ___, context) => {
63-
utils.websites.list.invalidate(context?.queryKey);
50+
onError: (error) => {
51+
console.error('Failed to create website:', error);
6452
},
6553
});
6654
}
6755

6856
export function useUpdateWebsite() {
6957
const utils = trpc.useUtils();
7058
return trpc.websites.update.useMutation({
71-
onMutate: async (updatedWebsite) => {
59+
onSuccess: (updatedWebsite) => {
7260
const getByIdKey = { id: updatedWebsite.id };
73-
await utils.websites.getById.cancel(getByIdKey);
74-
const previousWebsite = utils.websites.getById.getData(getByIdKey);
75-
7661
const listKey = {
77-
organizationId: previousWebsite?.organizationId ?? undefined,
62+
organizationId: updatedWebsite.organizationId ?? undefined,
7863
};
79-
await utils.websites.list.cancel(listKey);
80-
const previousWebsites = utils.websites.list.getData(listKey);
8164

8265
utils.websites.list.setData(listKey, (old) =>
8366
old?.map((website) =>
84-
website.id === updatedWebsite.id
85-
? { ...website, ...updatedWebsite }
86-
: website
87-
)
88-
);
89-
utils.websites.getById.setData(getByIdKey, (old) =>
90-
old ? { ...old, ...updatedWebsite } : undefined
67+
website.id === updatedWebsite.id ? updatedWebsite : website
68+
) ?? []
9169
);
92-
93-
return { previousWebsites, previousWebsite, listKey };
94-
},
95-
onError: (_, updatedWebsite, context) => {
96-
if (context?.previousWebsites && context.listKey) {
97-
utils.websites.list.setData(context.listKey, context.previousWebsites);
98-
}
99-
if (context?.previousWebsite) {
100-
utils.websites.getById.setData(
101-
{ id: updatedWebsite.id },
102-
context.previousWebsite
103-
);
104-
}
70+
71+
utils.websites.getById.setData(getByIdKey, updatedWebsite);
10572
},
106-
onSettled: (data, __, ___, context) => {
107-
utils.websites.list.invalidate(context?.listKey);
108-
if (data) {
109-
utils.websites.getById.invalidate({ id: data.id });
110-
}
73+
onError: (error) => {
74+
console.error('Failed to update website:', error);
11175
},
11276
});
11377
}
@@ -117,34 +81,29 @@ export function useDeleteWebsite() {
11781
return trpc.websites.delete.useMutation({
11882
onMutate: async ({ id }) => {
11983
const getByIdKey = { id };
120-
await utils.websites.getById.cancel(getByIdKey);
12184
const previousWebsite = utils.websites.getById.getData(getByIdKey);
12285

12386
const listKey = {
12487
organizationId: previousWebsite?.organizationId ?? undefined,
12588
};
89+
12690
await utils.websites.list.cancel(listKey);
12791
const previousWebsites = utils.websites.list.getData(listKey);
12892

12993
utils.websites.list.setData(
13094
listKey,
13195
(old) => old?.filter((w) => w.id !== id) ?? []
13296
);
133-
utils.websites.getById.setData(getByIdKey, undefined);
13497

135-
return { previousWebsites, previousWebsite, listKey };
98+
return { previousWebsites, listKey };
13699
},
137-
onError: (_, { id }, context) => {
100+
onError: (_, __, context) => {
138101
if (context?.previousWebsites && context.listKey) {
139102
utils.websites.list.setData(context.listKey, context.previousWebsites);
140103
}
141-
if (context?.previousWebsite) {
142-
utils.websites.getById.setData({ id }, context.previousWebsite);
143-
}
144104
},
145-
onSettled: (_, __, { id }, context) => {
146-
utils.websites.list.invalidate(context?.listKey);
147-
utils.websites.getById.invalidate({ id });
105+
onSuccess: (_, { id }) => {
106+
utils.websites.getById.setData({ id }, undefined);
148107
},
149108
});
150109
}

0 commit comments

Comments
 (0)