Skip to content

Commit 736ff6c

Browse files
authored
fixes: Fix deleting caps within folders and duplicate refresh route (#997)
* Fix deleting caps within folders and duplicate refresh route * Update schema.ts
1 parent cc7023b commit 736ff6c

File tree

4 files changed

+88
-58
lines changed

4 files changed

+88
-58
lines changed

apps/web/app/(org)/dashboard/caps/Caps.tsx

Lines changed: 33 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
88
import { useQuery } from "@tanstack/react-query";
99
import { Effect, Exit } from "effect";
1010
import { useRouter, useSearchParams } from "next/navigation";
11-
import { useEffect, useRef, useState } from "react";
11+
import { useEffect, useMemo, useRef, useState } from "react";
1212
import { toast } from "sonner";
1313
import { useEffectMutation } from "@/lib/EffectRuntime";
1414
import { Rpc, withRpc } from "@/lib/Rpcs";
@@ -266,6 +266,14 @@ export const Caps = ({
266266
},
267267
});
268268

269+
const visibleVideos = useMemo(
270+
() =>
271+
isUploading && uploadingCapId
272+
? data.filter((video) => video.id !== uploadingCapId)
273+
: data,
274+
[data, isUploading, uploadingCapId],
275+
);
276+
269277
if (count === 0) return <EmptyCapState />;
270278

271279
return (
@@ -312,7 +320,7 @@ export const Caps = ({
312320
</div>
313321
</>
314322
)}
315-
{data.length > 0 && (
323+
{visibleVideos.length > 0 && (
316324
<>
317325
<div className="flex justify-between items-center mb-6 w-full">
318326
<h1 className="text-2xl font-medium text-gray-12">Videos</h1>
@@ -322,31 +330,29 @@ export const Caps = ({
322330
{isUploading && (
323331
<UploadPlaceholderCard key={"upload-placeholder"} />
324332
)}
325-
{data
326-
.filter((cap) => !isUploading || cap.id !== uploadingCapId)
327-
.map((cap) => {
328-
return (
329-
<CapCard
330-
key={cap.id}
331-
cap={cap}
332-
analytics={analytics[cap.id] || 0}
333-
onDelete={() => {
334-
if (selectedCaps.length > 0) {
335-
deleteCaps(selectedCaps);
336-
} else {
337-
deleteCap(cap.id);
338-
}
339-
}}
340-
userId={user?.id}
341-
customDomain={customDomain}
342-
isLoadingAnalytics={isLoadingAnalytics}
343-
domainVerified={domainVerified}
344-
isSelected={selectedCaps.includes(cap.id)}
345-
anyCapSelected={anyCapSelected}
346-
onSelectToggle={() => handleCapSelection(cap.id)}
347-
/>
348-
);
349-
})}
333+
{visibleVideos.map((video) => {
334+
return (
335+
<CapCard
336+
key={video.id}
337+
cap={video}
338+
analytics={analytics[video.id] || 0}
339+
onDelete={() => {
340+
if (selectedCaps.length > 0) {
341+
deleteCaps(selectedCaps);
342+
} else {
343+
deleteCap(video.id);
344+
}
345+
}}
346+
userId={user?.id}
347+
customDomain={customDomain}
348+
isLoadingAnalytics={isLoadingAnalytics}
349+
domainVerified={domainVerified}
350+
isSelected={selectedCaps.includes(video.id)}
351+
anyCapSelected={anyCapSelected}
352+
onSelectToggle={() => handleCapSelection(video.id)}
353+
/>
354+
);
355+
})}
350356
</div>
351357
</>
352358
)}

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

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,9 @@ export const CapCard = ({
144144

145145
const duplicateMutation = useEffectMutation({
146146
mutationFn: () => withRpc((r) => r.VideoDuplicate(cap.id)),
147+
onSuccess: () => {
148+
router.refresh();
149+
},
147150
});
148151

149152
const handleSharingUpdated = () => {
@@ -336,13 +339,13 @@ export const CapCard = ({
336339

337340
<DropdownMenuContent align="end" sideOffset={5}>
338341
<DropdownMenuItem
339-
onClick={() =>
342+
onClick={() => {
340343
toast.promise(duplicateMutation.mutateAsync(), {
341344
loading: "Duplicating cap...",
342345
success: "Cap duplicated successfully",
343346
error: "Failed to duplicate cap",
344-
})
345-
}
347+
});
348+
}}
346349
disabled={duplicateMutation.isPending}
347350
className="flex gap-2 items-center rounded-lg"
348351
>

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

Lines changed: 47 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@ import type { Video } from "@cap/web-domain";
44
import { useQuery } from "@tanstack/react-query";
55
import { Effect, Exit } from "effect";
66
import { useRouter } from "next/navigation";
7-
import { useRef, useState } from "react";
7+
import { useMemo, useRef, useState } from "react";
88
import { toast } from "sonner";
99
import { useDashboardContext } from "@/app/(org)/dashboard/Contexts";
1010
import { useEffectMutation } from "@/lib/EffectRuntime";
11-
import { Rpc } from "@/lib/Rpcs";
11+
import { Rpc, withRpc } from "@/lib/Rpcs";
1212
import type { VideoData } from "../../../caps/Caps";
1313
import { CapCard } from "../../../caps/components/CapCard/CapCard";
1414
import { SelectedCapsBar } from "../../../caps/components/SelectedCapsBar";
@@ -28,12 +28,12 @@ export default function FolderVideosSection({
2828
}: FolderVideosSectionProps) {
2929
const router = useRouter();
3030
const { isUploading, uploadingCapId } = useUploadingContext();
31-
const { activeOrganization, user } = useDashboardContext();
31+
const { user } = useDashboardContext();
3232

3333
const [selectedCaps, setSelectedCaps] = useState<Video.VideoId[]>([]);
3434
const previousCountRef = useRef<number>(0);
3535

36-
const deleteCaps = useEffectMutation({
36+
const { mutate: deleteCaps, isPending: isDeletingCaps } = useEffectMutation({
3737
mutationFn: Effect.fn(function* (ids: Video.VideoId[]) {
3838
if (ids.length === 0) return;
3939

@@ -63,9 +63,7 @@ export default function FolderVideosSection({
6363
}).pipe(Effect.fork);
6464

6565
toast.promise(Effect.runPromise(fiber.await.pipe(Effect.flatten)), {
66-
loading: `Deleting ${selectedCaps.length} cap${
67-
selectedCaps.length === 1 ? "" : "s"
68-
}...`,
66+
loading: `Deleting ${ids.length} cap${ids.length === 1 ? "" : "s"}...`,
6967
success: (data) => {
7068
if (data.error) {
7169
return `Successfully deleted ${data.success} cap${
@@ -90,6 +88,17 @@ export default function FolderVideosSection({
9088
},
9189
});
9290

91+
const { mutate: deleteCap, isPending: isDeletingCap } = useEffectMutation({
92+
mutationFn: (id: Video.VideoId) => withRpc((r) => r.VideoDelete(id)),
93+
onSuccess: () => {
94+
toast.success("Cap deleted successfully");
95+
router.refresh();
96+
},
97+
onError: () => {
98+
toast.error("Failed to delete cap");
99+
},
100+
});
101+
93102
const handleCapSelection = (capId: Video.VideoId) => {
94103
setSelectedCaps((prev) => {
95104
const newSelection = prev.includes(capId)
@@ -146,6 +155,14 @@ export default function FolderVideosSection({
146155
refetchOnMount: true,
147156
});
148157

158+
const visibleVideos = useMemo(
159+
() =>
160+
isUploading && uploadingCapId
161+
? initialVideos.filter((video) => video.id !== uploadingCapId)
162+
: initialVideos,
163+
[initialVideos, isUploading, uploadingCapId],
164+
);
165+
149166
const analytics = analyticsData || {};
150167

151168
return (
@@ -154,7 +171,7 @@ export default function FolderVideosSection({
154171
<h1 className="text-2xl font-medium text-gray-12">Videos</h1>
155172
</div>
156173
<div className="grid grid-cols-1 gap-4 sm:gap-6 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 2xl:grid-cols-5">
157-
{initialVideos.length === 0 && !isUploading ? (
174+
{visibleVideos.length === 0 && !isUploading ? (
158175
<p className="col-span-full text-gray-9">
159176
No videos in this folder yet. Drag and drop into the folder or
160177
upload.
@@ -164,30 +181,34 @@ export default function FolderVideosSection({
164181
{isUploading && (
165182
<UploadPlaceholderCard key={"upload-placeholder"} />
166183
)}
167-
{initialVideos
168-
.filter((cap) => !isUploading || cap.id !== uploadingCapId)
169-
.map((video) => (
170-
<CapCard
171-
key={video.id}
172-
cap={video}
173-
analytics={analytics[video.id] || 0}
174-
userId={user?.id}
175-
isLoadingAnalytics={isLoadingAnalytics}
176-
isSelected={selectedCaps.includes(video.id)}
177-
anyCapSelected={selectedCaps.length > 0}
178-
isDeleting={deleteCaps.isPending}
179-
onSelectToggle={() => handleCapSelection(video.id)}
180-
onDelete={() => deleteCaps.mutateAsync(selectedCaps)}
181-
/>
182-
))}
184+
{visibleVideos.map((video) => (
185+
<CapCard
186+
key={video.id}
187+
cap={video}
188+
analytics={analytics[video.id] || 0}
189+
userId={user?.id}
190+
isLoadingAnalytics={isLoadingAnalytics}
191+
isSelected={selectedCaps.includes(video.id)}
192+
anyCapSelected={selectedCaps.length > 0}
193+
isDeleting={isDeletingCaps || isDeletingCap}
194+
onSelectToggle={() => handleCapSelection(video.id)}
195+
onDelete={() => {
196+
if (selectedCaps.length > 0) {
197+
deleteCaps(selectedCaps);
198+
} else {
199+
deleteCap(video.id);
200+
}
201+
}}
202+
/>
203+
))}
183204
</>
184205
)}
185206
</div>
186207
<SelectedCapsBar
187208
selectedCaps={selectedCaps}
188209
setSelectedCaps={setSelectedCaps}
189-
deleteSelectedCaps={() => deleteCaps.mutateAsync(selectedCaps)}
190-
isDeleting={deleteCaps.isPending}
210+
deleteSelectedCaps={() => deleteCaps(selectedCaps)}
211+
isDeleting={isDeletingCaps || isDeletingCap}
191212
/>
192213
</>
193214
);

packages/database/schema.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,8 @@ export const users = mysqlTable(
7272
pauseViews: boolean;
7373
pauseReactions: boolean;
7474
};
75-
// For analytics.
76-
// Adding in preferences so we don't have to
75+
// For analytics.
76+
// Adding in preferences so we don't have to
7777
// add a new column and can be dynamic going forward.
7878
trackedEvents?: {
7979
user_signed_up?: boolean;

0 commit comments

Comments
 (0)