diff --git a/actions/profile.ts b/actions/profile.ts index bf47cb4..be389be 100644 --- a/actions/profile.ts +++ b/actions/profile.ts @@ -8,7 +8,7 @@ import { revalidatePath } from "next/cache"; import { db } from "@/lib/db"; import { DEFAULT_THEME_ID } from "@/lib/constants"; import { requireCurrentUser } from "@/lib/session"; -import { normalizeUsername, safeUrl, sanitizeOptionalPlainText, sanitizePlainText } from "@/lib/sanitize"; +import { normalizeUsername, sanitizeOptionalPlainText, sanitizePlainText } from "@/lib/sanitize"; import { profileSchema } from "@/lib/validators/profile"; export type ActionResult = { @@ -81,12 +81,7 @@ export async function updateProfileAction(formData: FormData): Promise 0) { @@ -165,3 +160,36 @@ export async function updateProfileAction(formData: FormData): Promise { + const user = await requireCurrentUser(); + const currentUsername = user.profile?.username; + const existingAvatarUrl = user.profile?.avatarUrl ?? null; + + if (!user.profile) { + return { success: false, message: "Profile not found" }; + } + + if (!existingAvatarUrl) { + return { success: true, message: "Avatar is already empty" }; + } + + try { + await db.profile.update({ + where: { userId: user.id }, + data: { avatarUrl: null } + }); + + await deleteOldUploadedAvatar(existingAvatarUrl); + + if (currentUsername) { + revalidatePath(`/u/${currentUsername}`); + } + revalidatePath("/dashboard"); + revalidatePath("/dashboard/profile"); + + return { success: true, message: "Avatar reset" }; + } catch { + return { success: false, message: "Could not reset avatar" }; + } +} diff --git a/app/(dashboard)/dashboard/profile/page.tsx b/app/(dashboard)/dashboard/profile/page.tsx index ffc913b..f03ecb0 100644 --- a/app/(dashboard)/dashboard/profile/page.tsx +++ b/app/(dashboard)/dashboard/profile/page.tsx @@ -26,7 +26,6 @@ export default async function DashboardProfilePage() { username: profile?.username ?? "", displayName: profile?.displayName ?? "", bio: profile?.bio ?? "", - avatarUrl: profile?.avatarUrl ?? "", themeId: profile?.themeId ?? DEFAULT_THEME_ID, isPublic: profile?.isPublic ?? true }} diff --git a/components/dashboard/profile-form.tsx b/components/dashboard/profile-form.tsx index a7196f1..d8ccb95 100644 --- a/components/dashboard/profile-form.tsx +++ b/components/dashboard/profile-form.tsx @@ -1,7 +1,7 @@ "use client"; import { FormEvent, useState, useTransition } from "react"; -import { updateProfileAction } from "@/actions/profile"; +import { resetAvatarAction, updateProfileAction } from "@/actions/profile"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Select } from "@/components/ui/select"; @@ -18,7 +18,6 @@ type ProfileFormProps = { username: string; displayName: string; bio: string; - avatarUrl: string; themeId: string; isPublic: boolean; }; @@ -33,11 +32,23 @@ export function ProfileForm({ initialValues, themes }: ProfileFormProps) { const [username, setUsername] = useState(initialValues.username); const [displayName, setDisplayName] = useState(initialValues.displayName); const [bio, setBio] = useState(initialValues.bio); - const [avatarUrl, setAvatarUrl] = useState(initialValues.avatarUrl); const [avatarFile, setAvatarFile] = useState(null); const [themeId, setThemeId] = useState(initialValues.themeId); const [isPublic, setIsPublic] = useState(initialValues.isPublic); + function handleResetAvatar() { + setMessage(null); + + startTransition(async () => { + const result = await resetAvatarAction(); + setMessage(result.message); + setIsError(!result.success); + if (result.success) { + setAvatarFile(null); + } + }); + } + function onSubmit(event: FormEvent) { event.preventDefault(); setMessage(null); @@ -46,7 +57,6 @@ export function ProfileForm({ initialValues, themes }: ProfileFormProps) { formData.set("username", username); formData.set("displayName", displayName); formData.set("bio", bio); - formData.set("avatarUrl", avatarUrl); if (avatarFile) { formData.set("avatarFile", avatarFile); } @@ -103,16 +113,17 @@ export function ProfileForm({ initialValues, themes }: ProfileFormProps) { onChange={(event) => setAvatarFile(event.target.files?.[0] ?? null)} /> - - +
+ +