diff --git a/apps/web/actions/video/upload.ts b/apps/web/actions/video/upload.ts index 2bfa2f541..9bcd05a7c 100644 --- a/apps/web/actions/video/upload.ts +++ b/apps/web/actions/video/upload.ts @@ -164,6 +164,7 @@ export async function createVideoAndGetUploadUrl({ isScreenshot = false, isUpload = false, folderId, + orgId, }: { videoId?: Video.VideoId; duration?: number; @@ -173,6 +174,7 @@ export async function createVideoAndGetUploadUrl({ isScreenshot?: boolean; isUpload?: boolean; folderId?: Folder.FolderId; + orgId: string; }) { const user = await getCurrentUser(); @@ -228,6 +230,7 @@ export async function createVideoAndGetUploadUrl({ isScreenshot ? "Screenshot" : isUpload ? "Upload" : "Recording" } - ${formattedDate}`, ownerId: user.id, + orgId, source: { type: "desktopMP4" as const }, isScreenshot, bucket: customBucket?.id, diff --git a/apps/web/app/(org)/dashboard/caps/components/UploadCapButton.tsx b/apps/web/app/(org)/dashboard/caps/components/UploadCapButton.tsx index 80931b4c3..085d0dfb9 100644 --- a/apps/web/app/(org)/dashboard/caps/components/UploadCapButton.tsx +++ b/apps/web/app/(org)/dashboard/caps/components/UploadCapButton.tsx @@ -27,7 +27,7 @@ export const UploadCapButton = ({ grey?: boolean; folderId?: Folder.FolderId; }) => { - const { user } = useDashboardContext(); + const { user, activeOrganization } = useDashboardContext(); const inputRef = useRef(null); const { uploadingStore, setUploadStatus } = useUploadingContext(); const isUploading = useStore(uploadingStore, (s) => !!s.uploadStatus); @@ -52,9 +52,16 @@ export const UploadCapButton = ({ const file = e.target.files?.[0]; if (!file || !user) return; + // This should be unreachable. + if (activeOrganization === null) { + alert("No organization active!"); + return; + } + const ok = await legacyUploadCap( file, folderId, + activeOrganization.organization.id, setUploadStatus, queryClient, ); @@ -93,6 +100,7 @@ export const UploadCapButton = ({ async function legacyUploadCap( file: File, folderId: Folder.FolderId | undefined, + orgId: string, setUploadStatus: (state: UploadStatus | undefined) => void, queryClient: QueryClient, ) { @@ -127,6 +135,7 @@ async function legacyUploadCap( isScreenshot: false, isUpload: true, folderId, + orgId, }); const uploadId = videoData.id; @@ -451,6 +460,7 @@ async function legacyUploadCap( videoId: uploadId, isScreenshot: true, isUpload: true, + orgId, }); const screenshotFormData = new FormData(); diff --git a/apps/web/app/(org)/dashboard/dashboard-data.ts b/apps/web/app/(org)/dashboard/dashboard-data.ts index 7b8392c38..c581a783d 100644 --- a/apps/web/app/(org)/dashboard/dashboard-data.ts +++ b/apps/web/app/(org)/dashboard/dashboard-data.ts @@ -48,6 +48,7 @@ export async function getDashboardData(user: typeof userSelectProps) { email: users.email, inviteQuota: users.inviteQuota, image: users.image, + defaultOrgId: users.defaultOrgId, }, }) .from(organizations) diff --git a/apps/web/app/(org)/dashboard/settings/account/Settings.tsx b/apps/web/app/(org)/dashboard/settings/account/Settings.tsx index e97793dfe..384c78438 100644 --- a/apps/web/app/(org)/dashboard/settings/account/Settings.tsx +++ b/apps/web/app/(org)/dashboard/settings/account/Settings.tsx @@ -1,34 +1,47 @@ "use client"; import type { users } from "@cap/database/schema"; -import { Button, Card, CardDescription, CardTitle, Input } from "@cap/ui"; +import { + Button, + Card, + CardDescription, + CardTitle, + Input, + Select, +} from "@cap/ui"; import { useMutation } from "@tanstack/react-query"; import { useRouter } from "next/navigation"; -import { useState } from "react"; +import { useEffect, useState } from "react"; import { toast } from "sonner"; +import { useDashboardContext } from "../../Contexts"; +import { patchAccountSettings } from "./server"; export const Settings = ({ user, }: { user?: typeof users.$inferSelect | null; }) => { + const router = useRouter(); + const { organizationData } = useDashboardContext(); const [firstName, setFirstName] = useState(user?.name || ""); const [lastName, setLastName] = useState(user?.lastName || ""); - const router = useRouter(); + const [defaultOrgId, setDefaultOrgId] = useState( + user?.defaultOrgId || undefined, + ); + + // Track if form has unsaved changes + const hasChanges = + firstName !== (user?.name || "") || + lastName !== (user?.lastName || "") || + defaultOrgId !== user?.defaultOrgId; const { mutate: updateName, isPending: updateNamePending } = useMutation({ mutationFn: async () => { - const res = await fetch("/api/settings/user/name", { - method: "POST", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify({ - firstName: firstName.trim(), - lastName: lastName.trim() ? lastName.trim() : null, - }), - }); - if (!res.ok) { - throw new Error("Failed to update name"); - } + await patchAccountSettings( + firstName.trim(), + lastName.trim() ? lastName.trim() : undefined, + defaultOrgId, + ); }, onSuccess: () => { toast.success("Name updated successfully"); @@ -39,6 +52,19 @@ export const Settings = ({ }, }); + // Prevent navigation when there are unsaved changes + useEffect(() => { + const handleBeforeUnload = (e: BeforeUnloadEvent) => { + if (hasChanges) { + e.preventDefault(); + e.returnValue = ""; + } + }; + + window.addEventListener("beforeunload", handleBeforeUnload); + return () => window.removeEventListener("beforeunload", handleBeforeUnload); + }, [hasChanges]); + return (
{ @@ -91,9 +117,30 @@ export const Settings = ({ disabled /> + +
+ Default organization + This is the default organization +
+ +