|
@@ -136,7 +136,7 @@
|
|
|
<div class="absolute inset-0 bg-background/90 backdrop-blur-md" @click="showOrderEditModal = false" />
|
|
<div class="absolute inset-0 bg-background/90 backdrop-blur-md" @click="showOrderEditModal = false" />
|
|
|
<div class="relative w-full max-w-2xl bg-card border border-primary/30 rounded-3xl p-8 shadow-2xl overflow-y-auto max-h-[90vh]">
|
|
<div class="relative w-full max-w-2xl bg-card border border-primary/30 rounded-3xl p-8 shadow-2xl overflow-y-auto max-h-[90vh]">
|
|
|
<div class="flex justify-between items-center mb-6">
|
|
<div class="flex justify-between items-center mb-6">
|
|
|
- <h3 class="text-2xl font-black font-display text-gradient">Edit Order #{{ editingOrder?.id }}</h3>
|
|
|
|
|
|
|
+ <h3 class="text-2xl font-black font-display text-gradient">{{ t('admin.labels.editOrder') }} #{{ editingOrder?.id }}</h3>
|
|
|
<button @click="showOrderEditModal = false" class="p-2 hover:bg-white/5 rounded-full transition-colors"><X class="w-6 h-6" /></button>
|
|
<button @click="showOrderEditModal = false" class="p-2 hover:bg-white/5 rounded-full transition-colors"><X class="w-6 h-6" /></button>
|
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
@@ -194,7 +194,7 @@
|
|
|
<select v-model="orderForm.color_name" class="w-full bg-background border border-border/50 rounded-xl px-3 py-2 text-sm" :disabled="!orderForm.material_name">
|
|
<select v-model="orderForm.color_name" class="w-full bg-background border border-border/50 rounded-xl px-3 py-2 text-sm" :disabled="!orderForm.material_name">
|
|
|
<option value="">{{ t("admin.fields.colors") }}...</option>
|
|
<option value="">{{ t("admin.fields.colors") }}...</option>
|
|
|
<option v-for="c in materialColors" :key="c" :value="c">{{ c }}</option>
|
|
<option v-for="c in materialColors" :key="c" :value="c">{{ c }}</option>
|
|
|
- <option v-if="orderForm.color_name && !materialColors.includes(orderForm.color_name)" :value="orderForm.color_name">{{ orderForm.color_name }} (Current)</option>
|
|
|
|
|
|
|
+ <option v-if="orderForm.color_name && !materialColors.includes(orderForm.color_name)" :value="orderForm.color_name">{{ orderForm.color_name }} ({{ t('admin.labels.current') }})</option>
|
|
|
</select>
|
|
</select>
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
@@ -202,7 +202,7 @@
|
|
|
<!-- Review Feedback -->
|
|
<!-- Review Feedback -->
|
|
|
<div v-if="orderForm.review_text" class="p-4 bg-amber-500/5 border border-amber-500/20 rounded-2xl space-y-3">
|
|
<div v-if="orderForm.review_text" class="p-4 bg-amber-500/5 border border-amber-500/20 rounded-2xl space-y-3">
|
|
|
<div class="flex justify-between items-center">
|
|
<div class="flex justify-between items-center">
|
|
|
- <label class="text-[10px] font-bold uppercase text-amber-500 ml-1">Client Review Content</label>
|
|
|
|
|
|
|
+ <label class="text-[10px] font-bold uppercase text-amber-500 ml-1">{{ t('admin.labels.reviewContent') }}</label>
|
|
|
<div class="flex gap-1">
|
|
<div class="flex gap-1">
|
|
|
<Star v-for="i in 5" :key="i" class="w-3 h-3" :class="orderForm.rating >= i ? 'text-amber-500 fill-amber-500' : 'text-muted-foreground/20'" />
|
|
<Star v-for="i in 5" :key="i" class="w-3 h-3" :class="orderForm.rating >= i ? 'text-amber-500 fill-amber-500' : 'text-muted-foreground/20'" />
|
|
|
</div>
|
|
</div>
|
|
@@ -229,7 +229,7 @@
|
|
|
<button type="button" @click="handleDeleteFile(editingOrder.id, f.id, f.filename)" class="p-1.5 hover:bg-rose-500/10 rounded-md text-rose-500 transition-colors"><Trash2 class="w-3 h-3" /></button>
|
|
<button type="button" @click="handleDeleteFile(editingOrder.id, f.id, f.filename)" class="p-1.5 hover:bg-rose-500/10 rounded-md text-rose-500 transition-colors"><Trash2 class="w-3 h-3" /></button>
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
|
- <p v-if="!editingOrder?.files?.length" class="text-[10px] text-muted-foreground italic text-center py-4">No files attached</p>
|
|
|
|
|
|
|
+ <p v-if="!editingOrder?.files?.length" class="text-[10px] text-muted-foreground italic text-center py-4">{{ t('admin.labels.noFiles') }}</p>
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
@@ -249,7 +249,7 @@
|
|
|
<X class="w-2.5 h-2.5" />
|
|
<X class="w-2.5 h-2.5" />
|
|
|
</button>
|
|
</button>
|
|
|
</div>
|
|
</div>
|
|
|
- <p v-if="!editingOrder?.photos?.length" class="text-[10px] text-muted-foreground italic text-center py-4 w-full">No photos uploaded</p>
|
|
|
|
|
|
|
+ <p v-if="!editingOrder?.photos?.length" class="text-[10px] text-muted-foreground italic text-center py-4 w-full">{{ t('admin.labels.noPhotos') }}</p>
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
@@ -279,7 +279,7 @@
|
|
|
<label class="text-[10px] font-bold uppercase ml-1">{{ t("admin.fields.colors") }}</label>
|
|
<label class="text-[10px] font-bold uppercase ml-1">{{ t("admin.fields.colors") }}</label>
|
|
|
<div class="flex gap-2">
|
|
<div class="flex gap-2">
|
|
|
<input v-model="newColor" @keydown.enter.prevent="addColor" class="flex-1 bg-background border border-border/50 rounded-xl px-4 py-2 text-sm" placeholder="e.g. Red" />
|
|
<input v-model="newColor" @keydown.enter.prevent="addColor" class="flex-1 bg-background border border-border/50 rounded-xl px-4 py-2 text-sm" placeholder="e.g. Red" />
|
|
|
- <Button type="button" variant="hero" @click="addColor">Add</Button>
|
|
|
|
|
|
|
+ <Button type="button" variant="hero" @click="addColor">{{ t('admin.actions.add') }}</Button>
|
|
|
</div>
|
|
</div>
|
|
|
<div class="flex flex-wrap gap-2 mt-3">
|
|
<div class="flex flex-wrap gap-2 mt-3">
|
|
|
<span v-for="(c, idx) in matForm.available_colors" :key="idx" class="px-2 py-1 bg-primary/10 text-primary rounded-lg text-xs font-bold border border-primary/20 flex items-center gap-2">
|
|
<span v-for="(c, idx) in matForm.available_colors" :key="idx" class="px-2 py-1 bg-primary/10 text-primary rounded-lg text-xs font-bold border border-primary/20 flex items-center gap-2">
|
|
@@ -453,7 +453,7 @@ const orderForm = reactive({ total_price: 0, material_name: "", color_name: "",
|
|
|
const handleEditOrder = (order: any) => {
|
|
const handleEditOrder = (order: any) => {
|
|
|
editingOrder.value = order;
|
|
editingOrder.value = order;
|
|
|
Object.assign(orderForm, {
|
|
Object.assign(orderForm, {
|
|
|
- total_price: order.invoice_amount || 0,
|
|
|
|
|
|
|
+ total_price: Number(order.invoice_amount || 0),
|
|
|
material_name: order.material_name || "",
|
|
material_name: order.material_name || "",
|
|
|
color_name: order.color_name || "",
|
|
color_name: order.color_name || "",
|
|
|
quantity: order.quantity || 1,
|
|
quantity: order.quantity || 1,
|
|
@@ -679,7 +679,13 @@ async function handleSaveOrder() {
|
|
|
if (!editingOrder.value) return;
|
|
if (!editingOrder.value) return;
|
|
|
try {
|
|
try {
|
|
|
await adminUpdateOrder(editingOrder.value.id, orderForm);
|
|
await adminUpdateOrder(editingOrder.value.id, orderForm);
|
|
|
- closeModals(); fetchData();
|
|
|
|
|
|
|
+ // Optimistic local update
|
|
|
|
|
+ editingOrder.value.invoice_amount = orderForm.total_price;
|
|
|
|
|
+ const idx = orders.value.findIndex(o => o.id === editingOrder.value.id);
|
|
|
|
|
+ if (idx !== -1) orders.value[idx].invoice_amount = orderForm.total_price;
|
|
|
|
|
+
|
|
|
|
|
+ closeModals();
|
|
|
|
|
+ setTimeout(fetchData, 500); // Slight delay to ensure DB consistency
|
|
|
toast.success("Order updated");
|
|
toast.success("Order updated");
|
|
|
} catch (err: any) { toast.error(err.message); }
|
|
} catch (err: any) { toast.error(err.message); }
|
|
|
}
|
|
}
|