Compare commits
2 Commits
2f96552fe8
...
b537ca50cf
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b537ca50cf | ||
|
|
b9e6559bff |
@@ -3,19 +3,19 @@
|
||||
import { useState, useEffect } from 'react'
|
||||
import { useParams, useRouter } from 'next/navigation'
|
||||
import Link from 'next/link'
|
||||
import {
|
||||
Building2,
|
||||
Plus,
|
||||
Trash2,
|
||||
Loader2,
|
||||
Pencil,
|
||||
ArrowLeft,
|
||||
Search,
|
||||
MapPin,
|
||||
User,
|
||||
import {
|
||||
Building2,
|
||||
Plus,
|
||||
Trash2,
|
||||
Loader2,
|
||||
Pencil,
|
||||
ArrowLeft,
|
||||
Search,
|
||||
MapPin,
|
||||
User,
|
||||
Users,
|
||||
Briefcase,
|
||||
AlertCircle
|
||||
Briefcase,
|
||||
AlertCircle
|
||||
} from 'lucide-react'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { Input } from '@/components/ui/input'
|
||||
@@ -52,7 +52,7 @@ export default function CompanyCustomersPage() {
|
||||
// Dialog State
|
||||
const [isOpen, setIsOpen] = useState(false)
|
||||
const [editingCustomer, setEditingCustomer] = useState<any>(null)
|
||||
|
||||
|
||||
// Form State
|
||||
const [companyName, setCompanyName] = useState('')
|
||||
const [firstName, setFirstName] = useState('')
|
||||
@@ -62,6 +62,7 @@ export default function CompanyCustomersPage() {
|
||||
const [city, setCity] = useState('')
|
||||
const [vatId, setVatId] = useState('')
|
||||
const [partnerId, setPartnerId] = useState('')
|
||||
const [email, setEmail] = useState('')
|
||||
const [error, setError] = useState<string | null>(null)
|
||||
|
||||
const loadData = async () => {
|
||||
@@ -98,6 +99,7 @@ export default function CompanyCustomersPage() {
|
||||
setCity(customer ? customer.city || '' : '')
|
||||
setVatId(customer ? customer.vat_id || '' : '')
|
||||
setPartnerId(customer ? customer.partner_id || '' : (partners.length > 0 ? partners[0].id : ''))
|
||||
setEmail(customer ? customer.email || '' : '')
|
||||
setError(null)
|
||||
setIsOpen(true)
|
||||
}
|
||||
@@ -120,6 +122,7 @@ export default function CompanyCustomersPage() {
|
||||
zip: zip.trim() || undefined,
|
||||
city: city.trim() || undefined,
|
||||
vat_id: vatId.trim() || undefined,
|
||||
email: email.trim() || undefined,
|
||||
}
|
||||
|
||||
if (editingCustomer) {
|
||||
@@ -155,7 +158,8 @@ export default function CompanyCustomersPage() {
|
||||
const personMatch = `${c.first_name || ''} ${c.last_name || ''}`.toLowerCase().includes(q)
|
||||
const addressMatch = `${c.street || ''} ${c.zip || ''} ${c.city || ''}`.toLowerCase().includes(q)
|
||||
const partnerMatch = c.partner_name?.toLowerCase().includes(q)
|
||||
return nameMatch || personMatch || addressMatch || partnerMatch
|
||||
const emailMatch = c.email?.toLowerCase().includes(q)
|
||||
return nameMatch || personMatch || addressMatch || partnerMatch || emailMatch
|
||||
})
|
||||
|
||||
|
||||
@@ -164,8 +168,8 @@ export default function CompanyCustomersPage() {
|
||||
<div className="p-6 max-w-5xl mx-auto text-slate-900 dark:text-white space-y-8">
|
||||
{/* Back Link */}
|
||||
<div>
|
||||
<Link
|
||||
href="/admin/companies"
|
||||
<Link
|
||||
href="/admin/companies"
|
||||
className="inline-flex items-center gap-2 text-sm font-semibold text-slate-500 hover:text-slate-900 dark:text-slate-400 dark:hover:text-white transition-colors"
|
||||
>
|
||||
<ArrowLeft className="w-4 h-4" />
|
||||
@@ -199,7 +203,7 @@ export default function CompanyCustomersPage() {
|
||||
<div className="p-4 bg-amber-50 dark:bg-amber-950/20 border border-amber-200 dark:border-amber-900/30 rounded-xl flex gap-3 text-amber-800 dark:text-amber-300 text-sm">
|
||||
<AlertCircle className="w-5 h-5 shrink-0 text-amber-600 dark:text-amber-400" />
|
||||
<div>
|
||||
<p className="font-semibold">Keine Partner vorhanden</p>
|
||||
<p className="font-semibold">Keine Benutzer zugewiesen</p>
|
||||
<p className="mt-1">
|
||||
Diese Firma hat aktuell keine zugewiesenen Partner (Benutzer mit der Rolle "partner").
|
||||
Sie müssen zuerst in der <Link href="/admin/users" className="underline font-semibold hover:text-amber-900 dark:hover:text-amber-200">Benutzerverwaltung</Link> Partner erstellen und dieser Firma zuweisen, um Endkunden anzulegen.
|
||||
@@ -237,6 +241,7 @@ export default function CompanyCustomersPage() {
|
||||
<tr className="border-b border-slate-200 dark:border-white/10 text-slate-400 text-xs font-semibold uppercase">
|
||||
<th className="pb-3">Endkunde (Firma / Kontakt)</th>
|
||||
<th className="pb-3">Lieferadresse</th>
|
||||
<th className="pb-3">E-Mail</th>
|
||||
<th className="pb-3">USt-ID</th>
|
||||
<th className="pb-3">Zugeordneter Partner</th>
|
||||
<th className="pb-3 text-right">Aktionen</th>
|
||||
@@ -268,6 +273,9 @@ export default function CompanyCustomersPage() {
|
||||
<span className="text-slate-400 dark:text-slate-600">–</span>
|
||||
)}
|
||||
</td>
|
||||
<td className="py-4 text-sm text-slate-700 dark:text-slate-300">
|
||||
{customer.email || <span className="text-slate-400 dark:text-slate-600">–</span>}
|
||||
</td>
|
||||
<td className="py-4 text-sm text-slate-700 dark:text-slate-300">
|
||||
{customer.vat_id || <span className="text-slate-400 dark:text-slate-600">–</span>}
|
||||
</td>
|
||||
@@ -425,6 +433,18 @@ export default function CompanyCustomersPage() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="cust-email">E-Mail</Label>
|
||||
<Input
|
||||
id="cust-email"
|
||||
type="email"
|
||||
placeholder="kunde@beispiel.de"
|
||||
value={email}
|
||||
onChange={(e) => setEmail(e.target.value)}
|
||||
className="bg-slate-50 dark:bg-white/5 border-slate-200 dark:border-white/10"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{error && (
|
||||
<p className="text-sm text-red-600 dark:text-red-400">{error}</p>
|
||||
)}
|
||||
|
||||
@@ -21,7 +21,7 @@ export default function CustomerDetailPage({ params }: { params: Promise<{ id: s
|
||||
const [anonymizing, setAnonymizing] = useState(false)
|
||||
const [showGdprConfirm, setShowGdprConfirm] = useState(false)
|
||||
const [form, setForm] = useState({
|
||||
company_name: '', vat_id: '', first_name: '', last_name: '', street: '', zip: '', city: '',
|
||||
company_name: '', vat_id: '', first_name: '', last_name: '', street: '', zip: '', city: '', email: '',
|
||||
})
|
||||
|
||||
useEffect(() => {
|
||||
@@ -37,6 +37,7 @@ export default function CustomerDetailPage({ params }: { params: Promise<{ id: s
|
||||
street: c.street ?? '',
|
||||
zip: c.zip ?? '',
|
||||
city: c.city ?? '',
|
||||
email: c.email ?? '',
|
||||
})
|
||||
setLoading(false)
|
||||
})
|
||||
@@ -121,6 +122,7 @@ export default function CustomerDetailPage({ params }: { params: Promise<{ id: s
|
||||
{ label: 'USt-IdNr.', key: 'vat_id', span: false },
|
||||
{ label: 'Vorname', key: 'first_name', span: false },
|
||||
{ label: 'Nachname', key: 'last_name', span: false },
|
||||
{ label: 'E-Mail', key: 'email', span: true },
|
||||
{ label: 'Straße & Hausnummer', key: 'street', span: true },
|
||||
{ label: 'PLZ', key: 'zip', span: false },
|
||||
{ label: 'Ort', key: 'city', span: false },
|
||||
|
||||
@@ -14,7 +14,7 @@ export default function NewCustomerPage() {
|
||||
const router = useRouter()
|
||||
const [saving, setSaving] = useState(false)
|
||||
const [form, setForm] = useState({
|
||||
company_name: '', vat_id: '', first_name: '', last_name: '', street: '', zip: '', city: '',
|
||||
company_name: '', vat_id: '', first_name: '', last_name: '', street: '', zip: '', city: '', email: '',
|
||||
})
|
||||
|
||||
const handleSave = async () => {
|
||||
@@ -58,6 +58,7 @@ export default function NewCustomerPage() {
|
||||
{ label: 'USt-IdNr.', key: 'vat_id', span: false, placeholder: 'DE123456789' },
|
||||
{ label: 'Vorname', key: 'first_name', span: false, placeholder: '' },
|
||||
{ label: 'Nachname', key: 'last_name', span: false, placeholder: '' },
|
||||
{ label: 'E-Mail', key: 'email', span: true, placeholder: 'kunde@beispiel.de' },
|
||||
{ label: 'Straße & Hausnummer', key: 'street', span: true, placeholder: 'Musterstraße 1' },
|
||||
{ label: 'PLZ', key: 'zip', span: false, placeholder: '12345' },
|
||||
{ label: 'Ort', key: 'city', span: false, placeholder: 'Musterstadt' },
|
||||
|
||||
@@ -169,6 +169,7 @@ export async function adminCreateEndCustomer(data: {
|
||||
street?: string
|
||||
zip?: string
|
||||
city?: string
|
||||
email?: string
|
||||
}) {
|
||||
const admin = createAdminClient()
|
||||
const { data: dbData, error } = await admin
|
||||
@@ -182,6 +183,7 @@ export async function adminCreateEndCustomer(data: {
|
||||
street: data.street || null,
|
||||
zip: data.zip || null,
|
||||
city: data.city || null,
|
||||
email: data.email || null,
|
||||
}])
|
||||
.select()
|
||||
.single()
|
||||
@@ -198,6 +200,7 @@ export async function adminUpdateEndCustomer(id: string, data: {
|
||||
street?: string
|
||||
zip?: string
|
||||
city?: string
|
||||
email?: string
|
||||
}) {
|
||||
const admin = createAdminClient()
|
||||
const { data: dbData, error } = await admin
|
||||
@@ -211,6 +214,7 @@ export async function adminUpdateEndCustomer(id: string, data: {
|
||||
street: data.street || null,
|
||||
zip: data.zip || null,
|
||||
city: data.city || null,
|
||||
email: data.email || null,
|
||||
})
|
||||
.eq('id', id)
|
||||
.select()
|
||||
|
||||
@@ -15,6 +15,7 @@ export type EndCustomerFormData = {
|
||||
street?: string
|
||||
zip?: string
|
||||
city?: string
|
||||
email?: string
|
||||
}
|
||||
|
||||
// ─── Lesen ───────────────────────────────────────────────────────────────────
|
||||
@@ -72,6 +73,7 @@ export async function createEndCustomer(formData: EndCustomerFormData): Promise<
|
||||
street: formData.street || null,
|
||||
zip: formData.zip || null,
|
||||
city: formData.city || null,
|
||||
email: formData.email || null,
|
||||
}])
|
||||
.select()
|
||||
.single()
|
||||
@@ -101,6 +103,7 @@ export async function updateEndCustomer(id: string, formData: EndCustomerFormDat
|
||||
street: formData.street || null,
|
||||
zip: formData.zip || null,
|
||||
city: formData.city || null,
|
||||
email: formData.email || null,
|
||||
})
|
||||
.eq('id', id)
|
||||
|
||||
@@ -134,6 +137,7 @@ export async function anonymizeEndCustomer(id: string): Promise<void> {
|
||||
street: null,
|
||||
zip: null,
|
||||
city: null,
|
||||
email: null,
|
||||
is_anonymized: true,
|
||||
})
|
||||
.eq('id', id)
|
||||
|
||||
@@ -62,6 +62,7 @@ export type EndCustomer = {
|
||||
street: string | null
|
||||
zip: string | null
|
||||
city: string | null
|
||||
email?: string | null
|
||||
is_anonymized: boolean
|
||||
created_at: string
|
||||
}
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
-- Migration: Add email column to end_customers table
|
||||
ALTER TABLE public.end_customers
|
||||
ADD COLUMN IF NOT EXISTS email TEXT;
|
||||
Reference in New Issue
Block a user