feat: add hall logo support, fix fonts and build errors

This commit is contained in:
2025-12-07 15:57:01 +03:00
parent a0ed003a13
commit e263d2e235
20 changed files with 567 additions and 411 deletions

View File

@@ -0,0 +1,108 @@
"use client"
import { ChangeEvent, useState } from "react"
import { Button } from "@/components/ui/button"
import { createClient } from "@/lib/supabase/client"
import { ImagePlus, Loader2, X } from "lucide-react"
import Image from "next/image"
import { toast } from "sonner"
interface ImageUploadProps {
value: string
onChange: (url: string) => void
disabled?: boolean
bucketName?: string
}
export function ImageUpload({
value,
onChange,
disabled,
bucketName = "images"
}: ImageUploadProps) {
const [isUploading, setIsUploading] = useState(false)
const supabase = createClient()
const onUpload = async (e: ChangeEvent<HTMLInputElement>) => {
try {
const file = e.target.files?.[0]
if (!file) return
setIsUploading(true)
// 1. Dosya ismini benzersiz yap
const fileExt = file.name.split('.').pop()
const fileName = `${Math.random()}.${fileExt}`
const filePath = `${fileName}`
// 2. Upload
const { error: uploadError } = await supabase.storage
.from(bucketName)
.upload(filePath, file)
if (uploadError) {
throw uploadError
}
// 3. Public URL getir
const { data } = supabase.storage
.from(bucketName)
.getPublicUrl(filePath)
onChange(data.publicUrl)
toast.success("Resim yüklendi")
} catch (error) {
toast.error("Resim yüklenirken hata oluştu")
console.error(error)
} finally {
setIsUploading(false)
}
}
if (value) {
return (
<div className="relative w-[200px] h-[200px] rounded-md overflow-hidden border">
<div className="z-10 absolute top-2 right-2">
<Button
type="button"
onClick={() => onChange("")}
variant="destructive"
size="icon"
disabled={disabled}
>
<X className="h-4 w-4" />
</Button>
</div>
<Image
fill
className="object-cover"
alt="Image"
src={value}
/>
</div>
)
}
return (
<div className="w-[200px] h-[200px] rounded-md border-dashed border-2 flex items-center justify-center bg-muted/50 relative hover:opacity-75 transition disabled:opacity-50 disabled:cursor-not-allowed">
<input
type="file"
accept="image/*"
className="absolute inset-0 w-full h-full opacity-0 cursor-pointer disabled:cursor-not-allowed"
onChange={onUpload}
disabled={disabled || isUploading}
/>
{isUploading ? (
<div className="flex flex-col items-center gap-2">
<Loader2 className="h-4 w-4 animate-spin" />
<div className="text-xs text-muted-foreground">Yükleniyor...</div>
</div>
) : (
<div className="flex flex-col items-center gap-2">
<ImagePlus className="h-10 w-10 text-muted-foreground" />
<div className="text-xs text-muted-foreground">Resim Yükle</div>
</div>
)}
</div>
)
}

View File

@@ -1,10 +1,6 @@
'use client'
import {
Avatar,
AvatarFallback,
AvatarImage,
} from "@/components/ui/avatar"
// Avatar imports removed
import { Button } from "@/components/ui/button"
import {
DropdownMenu,
@@ -29,11 +25,8 @@ export function UserNav() {
return (
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="ghost" className="relative h-8 w-8 rounded-full">
<Avatar className="h-8 w-8">
<AvatarImage src="/avatars/01.png" alt="@shadcn" />
<AvatarFallback>AD</AvatarFallback>
</Avatar>
<Button variant="outline" className="relative">
Seçenekler
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent className="w-56" align="end" forceMount>