From 85df92249850922c93a54940f310f3739c8f0f16 Mon Sep 17 00:00:00 2001 From: DanielS Date: Thu, 25 Jun 2026 01:43:53 +0200 Subject: [PATCH] feat: make company selection mandatory for partner role and add inline company creation in UserDialog --- shop/components/admin/user-dialog.tsx | 195 ++++++++++++++++++-------- shop/lib/actions/companies.ts | 4 +- 2 files changed, 139 insertions(+), 60 deletions(-) diff --git a/shop/components/admin/user-dialog.tsx b/shop/components/admin/user-dialog.tsx index 1c37d98..1f99f20 100644 --- a/shop/components/admin/user-dialog.tsx +++ b/shop/components/admin/user-dialog.tsx @@ -25,6 +25,7 @@ import { import { Input } from '@/components/ui/input' import { Button } from '@/components/ui/button' import { createUser } from '@/lib/actions/users' +import { createCompany } from '@/lib/actions/companies' import { Plus, Building2 } from 'lucide-react' const userSchema = z.object({ @@ -33,6 +34,14 @@ const userSchema = z.object({ company_id: z.string().optional().or(z.literal('')), first_name: z.string().optional().or(z.literal('')), last_name: z.string().optional().or(z.literal('')), +}).refine((data) => { + if (data.role === 'partner' && !data.company_id) { + return false + } + return true +}, { + message: 'Für Partner-Benutzer ist eine Firmenauswahl erforderlich.', + path: ['company_id'], }) type UserFormValues = z.infer @@ -45,9 +54,17 @@ export function UserDialog({ companies }: UserDialogProps) { const [open, setOpen] = useState(false) const [dropdownOpen, setDropdownOpen] = useState(false) const [search, setSearch] = useState('') + const [localCompanies, setLocalCompanies] = useState<{ id: string; name: string }[]>(companies) + const [showNewCompanyInput, setShowNewCompanyInput] = useState(false) + const [newCompanyName, setNewCompanyName] = useState('') + const [isCreatingCompany, setIsCreatingCompany] = useState(false) const dropdownRef = useRef(null) const router = useRouter() + useEffect(() => { + setLocalCompanies(companies) + }, [companies]) + useEffect(() => { function handleClickOutside(e: MouseEvent) { if (dropdownRef.current && !dropdownRef.current.contains(e.target as Node)) { @@ -95,6 +112,8 @@ export function UserDialog({ companies }: UserDialogProps) { form.reset() setDropdownOpen(false) setSearch('') + setShowNewCompanyInput(false) + setNewCompanyName('') } }}> @@ -176,71 +195,131 @@ export function UserDialog({ companies }: UserDialogProps) { control={form.control} name="company_id" render={({ field }) => { - const selectedCompany = companies.find((c) => c.id === field.value) + const selectedCompany = localCompanies.find((c) => c.id === field.value) return ( - Firma (optional) + Firma -
-
- +
+
+
+ + +
+ {dropdownOpen && ( +
+
+ setSearch(e.target.value)} + className="w-full text-xs bg-white/5 border border-white/10 rounded px-2 py-1.5 text-slate-200 placeholder-slate-500 focus:outline-none focus:ring-1 focus:ring-primary/50" + autoFocus + /> +
+
+ + {localCompanies + .filter((c) => c.name.toLowerCase().includes(search.toLowerCase())) + .map((c) => ( + + ))} +
+
+ )} +
+ + {showNewCompanyInput ? ( +
+ setNewCompanyName(e.target.value)} + className="bg-white/5 border-white/10 text-white text-xs h-8" + /> + + +
+ ) : ( -
- {dropdownOpen && ( -
-
- setSearch(e.target.value)} - className="w-full text-xs bg-white/5 border border-white/10 rounded px-2 py-1.5 text-slate-200 placeholder-slate-500 focus:outline-none focus:ring-1 focus:ring-primary/50" - autoFocus - /> -
-
- - {companies - .filter((c) => c.name.toLowerCase().includes(search.toLowerCase())) - .map((c) => ( - - ))} -
-
)}
diff --git a/shop/lib/actions/companies.ts b/shop/lib/actions/companies.ts index 12d9170..d049da6 100644 --- a/shop/lib/actions/companies.ts +++ b/shop/lib/actions/companies.ts @@ -11,7 +11,7 @@ export async function getCompanies() { export async function createCompany(name: string) { const admin = createAdminClient() - const { data, error } = await admin.from('companies').insert({ name }).single() + const { data, error } = await admin.from('companies').insert({ name }).select().single() if (error) throw error revalidatePath('/admin/companies') return data @@ -19,7 +19,7 @@ export async function createCompany(name: string) { export async function updateCompany(id: string, name: string) { const admin = createAdminClient() - const { data, error } = await admin.from('companies').update({ name }).eq('id', id).single() + const { data, error } = await admin.from('companies').update({ name }).eq('id', id).select().single() if (error) throw error revalidatePath('/admin/companies') return data