"use client" import type { Organization } from "better-auth/plugins/organization" import { Trash2Icon, UploadCloudIcon } from "lucide-react" import { type ComponentProps, useContext, useMemo, useRef, useState } from "react" import { useCurrentOrganization } from "../../hooks/use-current-organization" import { AuthUIContext } from "../../lib/auth-ui-provider" import { fileToBase64, resizeAndCropImage } from "../../lib/image-utils" import { cn, getLocalizedError } from "../../lib/utils" import type { AuthLocalization } from "../../localization/auth-localization" import type { SettingsCardClassNames } from "../settings/shared/settings-card" import { SettingsCardFooter } from "../settings/shared/settings-card-footer" import { SettingsCardHeader } from "../settings/shared/settings-card-header" import { Button } from "../ui/button" import { Card } from "../ui/card" import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "../ui/dropdown-menu" import { OrganizationLogo } from "./organization-logo" export interface OrganizationLogoCardProps extends ComponentProps { className?: string classNames?: SettingsCardClassNames localization?: AuthLocalization slug?: string } export function OrganizationLogoCard({ className, classNames, localization: localizationProp, slug, ...props }: OrganizationLogoCardProps) { const { localization: contextLocalization } = useContext(AuthUIContext) const localization = useMemo( () => ({ ...contextLocalization, ...localizationProp }), [contextLocalization, localizationProp] ) const { data: organization } = useCurrentOrganization({ slug }) if (!organization) { return (
) } return ( ) } function OrganizationLogoForm({ className, classNames, localization: localizationProp, organization, ...props }: OrganizationLogoCardProps & { organization: Organization }) { const { hooks: { useHasPermission }, localization: authLocalization, organization: organizationOptions, mutators: { updateOrganization }, toast, localizeErrors } = useContext(AuthUIContext) const localization = useMemo( () => ({ ...authLocalization, ...localizationProp }), [authLocalization, localizationProp] ) const { refetch: refetchOrganization } = useCurrentOrganization({ slug: organization.slug }) const { data: hasPermission, isPending: permissionPending } = useHasPermission({ organizationId: organization.id, permissions: { organization: ["update"] } }) const isPending = permissionPending const fileInputRef = useRef(null) const [loading, setLoading] = useState(false) const handleLogoChange = async (file: File) => { if (!organizationOptions?.logo || !hasPermission?.success) return setLoading(true) const resizedFile = await resizeAndCropImage( file, crypto.randomUUID(), organizationOptions.logo.size, organizationOptions.logo.extension ) let image: string | undefined | null if (organizationOptions.logo.upload) { image = await organizationOptions.logo.upload(resizedFile) } else { image = await fileToBase64(resizedFile) } if (!image) { setLoading(false) return } try { await updateOrganization({ organizationId: organization.id, data: { logo: image } }) await refetchOrganization?.() } catch (error) { toast({ variant: "error", message: getLocalizedError({ error, localization, localizeErrors }) }) } setLoading(false) } const handleDeleteLogo = async () => { if (!hasPermission?.success) return setLoading(true) try { if (organization.logo) { await organizationOptions?.logo?.delete?.(organization.logo) } await updateOrganization({ organizationId: organization.id, data: { logo: "" } }) await refetchOrganization?.() } catch (error) { toast({ variant: "error", message: getLocalizedError({ error, localization, localizeErrors }) }) } setLoading(false) } const openFileDialog = () => { fileInputRef.current?.click() } return ( { const file = e.target.files?.item(0) if (file) handleLogoChange(file) e.target.value = "" }} />
e.preventDefault()} > {localization.UPLOAD_LOGO} {organization.logo && ( {localization.DELETE_LOGO} )}
) }