Add admin customer edit, status management, and admin notes
Adds edit/update endpoints for customer management with admin notes field, form request validation, status change audit logging, and 8 new tests (171 total, 846 assertions). Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
153
website/resources/ts/Pages/Admin/Customers/Edit.vue
Normal file
153
website/resources/ts/Pages/Admin/Customers/Edit.vue
Normal file
@@ -0,0 +1,153 @@
|
||||
<script lang="ts" setup>
|
||||
import { Link, useForm } from '@inertiajs/vue3'
|
||||
import AdminLayout from '@/Layouts/AdminLayout.vue'
|
||||
import AppTextField from '@/Components/app-form-elements/AppTextField.vue'
|
||||
import AppSelect from '@/Components/app-form-elements/AppSelect.vue'
|
||||
import AppTextarea from '@/Components/app-form-elements/AppTextarea.vue'
|
||||
import type { User } from '@/types'
|
||||
|
||||
defineOptions({ layout: AdminLayout })
|
||||
|
||||
interface Props {
|
||||
customer: User
|
||||
}
|
||||
|
||||
const props = defineProps<Props>()
|
||||
|
||||
const form = useForm({
|
||||
name: props.customer.name,
|
||||
email: props.customer.email,
|
||||
phone: props.customer.phone ?? '',
|
||||
company: props.customer.company ?? '',
|
||||
status: props.customer.status,
|
||||
admin_notes: props.customer.admin_notes ?? '',
|
||||
})
|
||||
|
||||
const statusOptions = [
|
||||
{ title: 'Active', value: 'active' },
|
||||
{ title: 'Suspended', value: 'suspended' },
|
||||
{ title: 'Banned', value: 'banned' },
|
||||
]
|
||||
|
||||
function submit(): void {
|
||||
form.put(`/customers/${props.customer.id}`)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<!-- Header -->
|
||||
<div class="d-flex align-center justify-space-between mb-6">
|
||||
<div>
|
||||
<div class="d-flex align-center gap-2 mb-1">
|
||||
<Link :href="`/customers/${customer.id}`" class="text-decoration-none">
|
||||
<VBtn icon="tabler-arrow-left" variant="text" size="small" />
|
||||
</Link>
|
||||
<span class="text-h4 font-weight-bold">Edit Customer</span>
|
||||
</div>
|
||||
<div class="text-body-2 text-medium-emphasis ms-10">
|
||||
Update details for "{{ customer.name }}"
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<form @submit.prevent="submit">
|
||||
<VRow>
|
||||
<!-- Customer Details -->
|
||||
<VCol cols="12" lg="8">
|
||||
<VCard title="Customer Details" class="mb-6">
|
||||
<VCardText>
|
||||
<VRow>
|
||||
<VCol cols="12" md="6">
|
||||
<AppTextField
|
||||
v-model="form.name"
|
||||
label="Name"
|
||||
placeholder="Full name"
|
||||
:error-messages="form.errors.name"
|
||||
/>
|
||||
</VCol>
|
||||
<VCol cols="12" md="6">
|
||||
<AppTextField
|
||||
v-model="form.email"
|
||||
label="Email"
|
||||
type="email"
|
||||
placeholder="email@example.com"
|
||||
:error-messages="form.errors.email"
|
||||
/>
|
||||
</VCol>
|
||||
<VCol cols="12" md="6">
|
||||
<AppTextField
|
||||
v-model="form.phone"
|
||||
label="Phone"
|
||||
placeholder="Phone number"
|
||||
:error-messages="form.errors.phone"
|
||||
/>
|
||||
</VCol>
|
||||
<VCol cols="12" md="6">
|
||||
<AppTextField
|
||||
v-model="form.company"
|
||||
label="Company"
|
||||
placeholder="Company name"
|
||||
:error-messages="form.errors.company"
|
||||
/>
|
||||
</VCol>
|
||||
<VCol cols="12" md="6">
|
||||
<AppSelect
|
||||
v-model="form.status"
|
||||
label="Status"
|
||||
:items="statusOptions"
|
||||
:error-messages="form.errors.status"
|
||||
/>
|
||||
</VCol>
|
||||
</VRow>
|
||||
</VCardText>
|
||||
</VCard>
|
||||
|
||||
<!-- Admin Notes -->
|
||||
<VCard title="Admin Notes" class="mb-6">
|
||||
<VCardText>
|
||||
<AppTextarea
|
||||
v-model="form.admin_notes"
|
||||
label="Internal Notes"
|
||||
placeholder="Add internal notes about this customer (only visible to admins)..."
|
||||
rows="4"
|
||||
:error-messages="form.errors.admin_notes"
|
||||
/>
|
||||
<div class="text-caption text-medium-emphasis mt-2">
|
||||
These notes are only visible to administrators and will not be shown to the customer.
|
||||
</div>
|
||||
</VCardText>
|
||||
</VCard>
|
||||
</VCol>
|
||||
|
||||
<!-- Sidebar -->
|
||||
<VCol cols="12" lg="4">
|
||||
<!-- Actions -->
|
||||
<VCard>
|
||||
<VCardText>
|
||||
<VBtn
|
||||
type="submit"
|
||||
color="primary"
|
||||
block
|
||||
:loading="form.processing"
|
||||
:disabled="form.processing"
|
||||
prepend-icon="tabler-check"
|
||||
class="mb-3"
|
||||
>
|
||||
Save Changes
|
||||
</VBtn>
|
||||
<Link :href="`/customers/${customer.id}`" class="text-decoration-none">
|
||||
<VBtn
|
||||
variant="outlined"
|
||||
block
|
||||
>
|
||||
Cancel
|
||||
</VBtn>
|
||||
</Link>
|
||||
</VCardText>
|
||||
</VCard>
|
||||
</VCol>
|
||||
</VRow>
|
||||
</form>
|
||||
</div>
|
||||
</template>
|
||||
@@ -23,6 +23,7 @@ interface Customer {
|
||||
email: string
|
||||
phone: string | null
|
||||
company: string | null
|
||||
admin_notes: string | null
|
||||
status: string
|
||||
created_at: string
|
||||
email_verified_at: string | null
|
||||
@@ -230,6 +231,16 @@ function formatBillingAddress(profile: CustomerProfile | null): string {
|
||||
</div>
|
||||
|
||||
<div class="d-flex align-center ga-2">
|
||||
<Link :href="`/customers/${customer.id}/edit`" class="text-decoration-none">
|
||||
<VBtn
|
||||
color="primary"
|
||||
variant="tonal"
|
||||
size="small"
|
||||
>
|
||||
<VIcon icon="tabler-edit" start />
|
||||
Edit
|
||||
</VBtn>
|
||||
</Link>
|
||||
<VBtn
|
||||
color="info"
|
||||
variant="tonal"
|
||||
@@ -390,6 +401,19 @@ function formatBillingAddress(profile: CustomerProfile | null): string {
|
||||
</VCardText>
|
||||
</VCard>
|
||||
|
||||
<!-- Admin Notes -->
|
||||
<VCard v-if="customer.admin_notes" class="mb-4">
|
||||
<VCardTitle class="d-flex align-center gap-2">
|
||||
<VIcon icon="tabler-notes" size="22" />
|
||||
<span>Admin Notes</span>
|
||||
</VCardTitle>
|
||||
<VCardText>
|
||||
<div class="text-body-2" style="white-space: pre-line;">
|
||||
{{ customer.admin_notes }}
|
||||
</div>
|
||||
</VCardText>
|
||||
</VCard>
|
||||
|
||||
<!-- Quick Stats -->
|
||||
<VCard>
|
||||
<VCardTitle class="d-flex align-center gap-2">
|
||||
|
||||
Reference in New Issue
Block a user