Skip to content

Commit 74c2ff7

Browse files
committed
move createFolder action to effect rpc
1 parent 801757a commit 74c2ff7

File tree

9 files changed

+155
-175
lines changed

9 files changed

+155
-175
lines changed

apps/web/actions/caps/get-shared-spaces.ts

Lines changed: 0 additions & 65 deletions
This file was deleted.

apps/web/actions/folders/createFolder.ts

Lines changed: 0 additions & 62 deletions
This file was deleted.

apps/web/app/(org)/dashboard/caps/components/NewFolderDialog.tsx

Lines changed: 33 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { useEffectMutation } from "@/lib/EffectRuntime";
2+
import { withRpc } from "@/lib/Rpcs";
13
import {
24
Button,
35
Dialog,
@@ -7,12 +9,14 @@ import {
79
DialogTitle,
810
Input,
911
} from "@cap/ui";
12+
import type { Folder } from "@cap/web-domain";
1013
import { faFolderPlus } from "@fortawesome/free-solid-svg-icons";
1114
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
1215
import clsx from "clsx";
16+
import { Option } from "effect";
17+
import { useRouter } from "next/navigation";
1318
import React, { useEffect, useRef, useState } from "react";
1419
import { toast } from "sonner";
15-
import { createFolder } from "@/actions/folders/createFolder";
1620
import { BlueFolder, NormalFolder, RedFolder, YellowFolder } from "./Folders";
1721

1822
interface Props {
@@ -54,31 +58,33 @@ export const NewFolderDialog: React.FC<Props> = ({
5458
>(null);
5559
const [folderName, setFolderName] = useState<string>("");
5660
const folderRefs = useRef<Record<string, any>>({});
57-
const [loading, setLoading] = useState<boolean>(false);
61+
const router = useRouter();
5862

5963
useEffect(() => {
6064
if (!open) setSelectedColor(null);
6165
}, [open]);
6266

63-
const createFolderHandler = async () => {
64-
if (!selectedColor) return;
65-
try {
66-
setLoading(true);
67-
await createFolder({
68-
name: folderName,
69-
color: selectedColor,
70-
spaceId,
71-
});
67+
const createFolder = useEffectMutation({
68+
mutationFn: (data: { name: string; color: Folder.FolderColor }) =>
69+
withRpc((r) =>
70+
r.FolderCreate({
71+
name: data.name,
72+
color: data.color,
73+
spaceId: Option.fromNullable(spaceId),
74+
parentId: Option.none(),
75+
}),
76+
),
77+
onSuccess: () => {
7278
setFolderName("");
7379
setSelectedColor(null);
7480
onOpenChange(false);
81+
router.refresh();
7582
toast.success("Folder created successfully");
76-
} catch (error: any) {
83+
},
84+
onError: () => {
7785
toast.error("Failed to create folder");
78-
} finally {
79-
setLoading(false);
80-
}
81-
};
86+
},
87+
});
8288

8389
return (
8490
<Dialog open={open} onOpenChange={onOpenChange}>
@@ -141,13 +147,20 @@ export const NewFolderDialog: React.FC<Props> = ({
141147
Cancel
142148
</Button>
143149
<Button
144-
onClick={createFolderHandler}
150+
onClick={() => {
151+
if (selectedColor === null) return;
152+
createFolder.mutate({ name: folderName, color: selectedColor });
153+
}}
145154
size="sm"
146-
spinner={loading}
155+
spinner={createFolder.isPending}
147156
variant="dark"
148-
disabled={!selectedColor || !folderName.trim().length || loading}
157+
disabled={
158+
!selectedColor ||
159+
!folderName.trim().length ||
160+
createFolder.isPending
161+
}
149162
>
150-
{loading ? "Creating..." : "Create"}
163+
{createFolder.isPending ? "Creating..." : "Create"}
151164
</Button>
152165
</DialogFooter>
153166
</DialogContent>

apps/web/app/(org)/dashboard/folder/[id]/components/SubfolderDialog.tsx

Lines changed: 36 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -14,19 +14,23 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
1414
import clsx from "clsx";
1515
import React, { useEffect, useRef, useState } from "react";
1616
import { toast } from "sonner";
17-
import { createFolder } from "@/actions/folders/createFolder";
1817
import { useDashboardContext } from "../../../Contexts";
1918
import {
2019
BlueFolder,
2120
NormalFolder,
2221
RedFolder,
2322
YellowFolder,
2423
} from "../../../caps/components/Folders";
24+
import { useEffectMutation } from "@/lib/EffectRuntime";
25+
import { Folder } from "@cap/web-domain";
26+
import { Option } from "effect";
27+
import { withRpc } from "@/lib/Rpcs";
28+
import { useRouter } from "next/navigation";
2529

2630
interface Props {
2731
open: boolean;
2832
onOpenChange: (open: boolean) => void;
29-
parentFolderId: string;
33+
parentFolderId: Folder.FolderId;
3034
}
3135

3236
const FolderOptions = [
@@ -62,8 +66,8 @@ export const SubfolderDialog: React.FC<Props> = ({
6266
>(null);
6367
const [folderName, setFolderName] = useState<string>("");
6468
const folderRefs = useRef<Record<string, any>>({});
65-
const [loading, setLoading] = useState<boolean>(false);
6669
const { activeSpace } = useDashboardContext();
70+
const router = useRouter();
6771

6872
useEffect(() => {
6973
if (!open) {
@@ -72,26 +76,27 @@ export const SubfolderDialog: React.FC<Props> = ({
7276
}
7377
}, [open]);
7478

75-
const createSubfolderHandler = async () => {
76-
if (!selectedColor) return;
77-
try {
78-
setLoading(true);
79-
await createFolder({
80-
name: folderName,
81-
color: selectedColor,
82-
parentId: parentFolderId,
83-
spaceId: activeSpace?.id,
84-
});
79+
const createSubfolder = useEffectMutation({
80+
mutationFn: (data: { name: string; color: Folder.FolderColor }) =>
81+
withRpc((r) =>
82+
r.FolderCreate({
83+
name: data.name,
84+
color: data.color,
85+
spaceId: Option.fromNullable(activeSpace?.id),
86+
parentId: Option.some(parentFolderId),
87+
}),
88+
),
89+
onSuccess: () => {
8590
setFolderName("");
8691
setSelectedColor(null);
8792
onOpenChange(false);
93+
router.refresh();
8894
toast.success("Subfolder created successfully");
89-
} catch (error: any) {
95+
},
96+
onError: () => {
9097
toast.error("Failed to create subfolder");
91-
} finally {
92-
setLoading(false);
93-
}
94-
};
98+
},
99+
});
95100

96101
return (
97102
<Dialog open={open} onOpenChange={onOpenChange}>
@@ -154,11 +159,21 @@ export const SubfolderDialog: React.FC<Props> = ({
154159
Cancel
155160
</Button>
156161
<Button
157-
onClick={createSubfolderHandler}
162+
onClick={() => {
163+
if (selectedColor === null) return;
164+
createSubfolder.mutate({
165+
name: folderName,
166+
color: selectedColor,
167+
});
168+
}}
158169
size="sm"
159-
spinner={loading}
170+
spinner={createSubfolder.isPending}
160171
variant="dark"
161-
disabled={!selectedColor || !folderName.trim().length || loading}
172+
disabled={
173+
!selectedColor ||
174+
!folderName.trim().length ||
175+
createSubfolder.isPending
176+
}
162177
>
163178
Create
164179
</Button>

packages/web-backend/src/Auth.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,11 @@ export const HttpAuthMiddlewareLive = Layer.effect(
4545
),
4646
);
4747

48-
return { id: user.id, email: user.email };
48+
return {
49+
id: user.id,
50+
email: user.email,
51+
activeOrgId: user.activeOrganizationId,
52+
};
4953
}).pipe(
5054
Effect.provideService(Database, database),
5155
Effect.catchTags({
@@ -70,6 +74,7 @@ export const provideOptionalAuth = <E, R>(
7074
CurrentUser.context({
7175
id: user.id,
7276
email: user.email,
77+
activeOrgId: user.activeOrganizationId,
7378
}),
7479
),
7580
Option.match({

packages/web-backend/src/Folders/FoldersRpcs.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,12 @@ export const FolderRpcsLive = Folder.FolderRpcs.toLayer(
1717
() => new InternalError({ type: "database" }),
1818
),
1919
),
20+
FolderCreate: data => folders.create(data).pipe(
21+
Effect.catchTag(
22+
"DatabaseError",
23+
() => new InternalError({ type: "database" }),
24+
),
25+
),
2026
};
2127
}),
2228
);

0 commit comments

Comments
 (0)