From 4e86ad7a9da16d1c666f71fc9a93e21d10c88350 Mon Sep 17 00:00:00 2001 From: DanielS Date: Wed, 24 Jun 2026 22:29:51 +0200 Subject: [PATCH] Rename companies to partners and update UI --- shop/app/admin/companies/page.tsx | 2 +- shop/app/admin/layout.tsx | 4 - shop/app/admin/partners/page.tsx | 180 ++++++++++++++++++ shop/lib/actions/partners.ts | 49 +++++ .../20260624100000_create_companies_table.sql | 14 +- 5 files changed, 237 insertions(+), 12 deletions(-) create mode 100644 shop/app/admin/partners/page.tsx create mode 100644 shop/lib/actions/partners.ts diff --git a/shop/app/admin/companies/page.tsx b/shop/app/admin/companies/page.tsx index 59f9228..0228bd5 100644 --- a/shop/app/admin/companies/page.tsx +++ b/shop/app/admin/companies/page.tsx @@ -30,7 +30,7 @@ export default function CompaniesPage() { const data = await getCompanies() setCompanies(data) } catch (err) { - console.error('Fehler beim Laden der Firmen:', err) + console.error('Fehler beim Laden der Partner:', err) } finally { setLoading(false) } diff --git a/shop/app/admin/layout.tsx b/shop/app/admin/layout.tsx index db2ee24..323b3df 100644 --- a/shop/app/admin/layout.tsx +++ b/shop/app/admin/layout.tsx @@ -58,10 +58,6 @@ export default async function AdminLayout({ Benutzer - - - Firmen -
Einstellungen diff --git a/shop/app/admin/partners/page.tsx b/shop/app/admin/partners/page.tsx new file mode 100644 index 0000000..166f8b8 --- /dev/null +++ b/shop/app/admin/partners/page.tsx @@ -0,0 +1,180 @@ +'use client' + +import { useState, useEffect } from 'react' +import { Building2, Plus, Trash2, Loader2 } from 'lucide-react' +import { Button } from '@/components/ui/button' +import { Input } from '@/components/ui/input' +import { Label } from '@/components/ui/label' +import { + Dialog, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, +} from '@/components/ui/dialog' +import { getPartners, createPartner, deletePartner } from '@/lib/actions/partners' + +export default function PartnersPage() { + const [partners, setPartners] = useState([]) + const [loading, setLoading] = useState(true) + const [isCreateOpen, setIsCreateOpen] = useState(false) + const [name, setName] = useState('') + const [creating, setCreating] = useState(false) + const [createError, setCreateError] = useState(null) + const [deletingId, setDeletingId] = useState(null) + + const loadPartners = async () => { + setLoading(true) + try { + const data = await getPartners() + setPartners(data) + } catch (err) { + console.error('Fehler beim Laden der Partner:', err) + } finally { + setLoading(false) + } + } + + useEffect(() => { + loadPartners() + }, []) + + const handleCreate = async (e: React.FormEvent) => { + e.preventDefault() + setCreating(true) + setCreateError(null) + try { + await createPartner(name) + setIsCreateOpen(false) + setName('') + loadPartners() + } catch (err: any) { + setCreateError(err.message || 'Fehler beim Anlegen.') + } finally { + setCreating(false) + } + } + + const handleDelete = async (id: string, partnerName: string) => { + if (!confirm(`Partner "${partnerName}" wirklich löschen?`)) return + setDeletingId(id) + try { + await deletePartner(id) + loadPartners() + } catch (err) { + console.error('Fehler beim Löschen:', err) + } finally { + setDeletingId(null) + } + } + + return ( +
+ {/* Header */} +
+
+

+ Partnerverwaltung +

+

+ Verwalten Sie Partner. +

+
+ +
+ + {/* Partner Table */} +
+ {loading ? ( +
+ + Lade Partner… +
+ ) : partners.length === 0 ? ( +
+ + Noch keine Partner angelegt. +
+ ) : ( + + + + + + + + + + {partners.map((partner) => ( + + + + + + ))} + +
PartnernameErstellt amAktionen
+
+ + {partner.name} +
+
+ {partner.created_at ? new Date(partner.created_at).toLocaleDateString('de-DE') : '–'} + + +
+ )} +
+ + {/* Dialog: Neuer Partner */} + + + + Neuen Partner anlegen + + Geben Sie den Namen des Partners ein. + + +
+
+ + setName(e.target.value)} + className="bg-slate-50 dark:bg-white/5 border-slate-200 dark:border-white/10" + /> +
+ {createError && ( +

{createError}

+ )} + + + + +
+
+
+
+ ) +} diff --git a/shop/lib/actions/partners.ts b/shop/lib/actions/partners.ts new file mode 100644 index 0000000..13c03de --- /dev/null +++ b/shop/lib/actions/partners.ts @@ -0,0 +1,49 @@ +'use server' + +import { createAdminClient } from '@/lib/supabase/admin' +import { revalidatePath } from 'next/cache' + +export async function getPartners() { + const admin = createAdminClient() + const { data, error } = await admin + .from('partners') + .select('id, name, created_at') + .order('name', { ascending: true }) + if (error) throw error + return data || [] +} + +export async function createPartner(name: string) { + const admin = createAdminClient() + const { data, error } = await admin + .from('partners') + .insert({ name: name.trim() }) + .select() + .single() + if (error) throw error + revalidatePath('/admin/partners') + revalidatePath('/admin/users') + return data +} + +export async function deletePartner(id: string) { + const admin = createAdminClient() + const { error } = await admin + .from('partners') + .delete() + .eq('id', id) + if (error) throw error + revalidatePath('/admin/partners') + revalidatePath('/admin/users') +} + +export async function assignPartnerToUser(userId: string, partnerId: string | null) { + const admin = createAdminClient() + const { error } = await admin + .from('users') + .update({ partner_id: partnerId }) + .eq('id', userId) + if (error) throw error + revalidatePath('/admin/users') + revalidatePath('/admin/einstellungen') +} diff --git a/shop/supabase/migrations/20260624100000_create_companies_table.sql b/shop/supabase/migrations/20260624100000_create_companies_table.sql index d41e85a..8cdeb83 100644 --- a/shop/supabase/migrations/20260624100000_create_companies_table.sql +++ b/shop/supabase/migrations/20260624100000_create_companies_table.sql @@ -1,7 +1,7 @@ -- Migration: companies table + company_id in users -- 1. Tabelle companies erstellen -CREATE TABLE IF NOT EXISTS public.companies ( +CREATE TABLE IF NOT EXISTS public.partners ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), name TEXT NOT NULL, created_at TIMESTAMPTZ NOT NULL DEFAULT now() @@ -11,21 +11,21 @@ CREATE TABLE IF NOT EXISTS public.companies ( ALTER TABLE public.companies ENABLE ROW LEVEL SECURITY; -- Policies -DROP POLICY IF EXISTS "Admins und Partner lesen Firmen" ON public.companies; -DROP POLICY IF EXISTS "Service role kann alles" ON public.companies; +DROP POLICY IF EXISTS "Admins und Partner lesen Partner" ON public.partners; +DROP POLICY IF EXISTS "Service role kann alles" ON public.partners; -CREATE POLICY "Admins und Partner lesen Firmen" - ON public.companies FOR SELECT +CREATE POLICY "Admins und Partner lesen Partner" + ON public.partners FOR SELECT USING (auth.role() = 'authenticated'); CREATE POLICY "Service role kann alles" - ON public.companies FOR ALL + ON public.partners FOR ALL USING (true) WITH CHECK (true); -- 2. company_id zu public.users hinzufügen ALTER TABLE public.users - ADD COLUMN IF NOT EXISTS company_id UUID REFERENCES public.companies(id) ON DELETE SET NULL; + ADD COLUMN IF NOT EXISTS partner_id UUID REFERENCES public.partners(id) ON DELETE SET NULL; -- Reload Schema Cache NOTIFY pgrst, 'reload schema';