chore: install prettier
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
<script setup>
|
||||
const props = defineProps({
|
||||
order: Object
|
||||
order: Object,
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -8,12 +8,14 @@ const props = defineProps({
|
||||
<div class="is-flex is-flex-direction-column is-gap-2">
|
||||
<div class="p-4 rounded-md has-background-primary-95">
|
||||
<p class="has-text-grey">Trạng thái</p>
|
||||
<p class="fs-17 mt-1 font-semibold has-text-primary-50">{{ order.delivery_status__name }}</p>
|
||||
<p class="fs-17 mt-1 font-semibold has-text-primary-50">
|
||||
{{ order.delivery_status__name }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="p-4 rounded-md has-background-grey-95">
|
||||
<p class="has-text-grey">Địa chỉ giao hàng</p>
|
||||
<p class="mt-1 has-text-grey-10">{{ order.customer__name }}</p>
|
||||
<p class="has-text-grey-10">{{ order.customer__phone }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -4,9 +4,8 @@ const props = defineProps({
|
||||
value: Number,
|
||||
icon: String,
|
||||
color: String,
|
||||
unit: String
|
||||
})
|
||||
|
||||
unit: String,
|
||||
});
|
||||
</script>
|
||||
<template>
|
||||
<div class="cell">
|
||||
@@ -19,8 +18,9 @@ const props = defineProps({
|
||||
<span class="fs-13 has-text-grey">{{ unit }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
:class="['p-3 is-flex', `has-background-${color}-soft`]" style="border-radius: 8px"
|
||||
<div
|
||||
:class="['p-3 is-flex', `has-background-${color}-soft`]"
|
||||
style="border-radius: 8px"
|
||||
>
|
||||
<Icon
|
||||
:name="icon"
|
||||
@@ -31,4 +31,4 @@ const props = defineProps({
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script setup>
|
||||
const props = defineProps({
|
||||
order: Object
|
||||
order: Object,
|
||||
});
|
||||
|
||||
const { $dayjs } = useNuxtApp();
|
||||
@@ -8,52 +8,52 @@ const { $dayjs } = useNuxtApp();
|
||||
const historyItems = [
|
||||
{
|
||||
id: 1,
|
||||
name: 'Tạo đơn hàng',
|
||||
details: 'Đơn hàng được tạo',
|
||||
icon: 'material-symbols:info-outline-rounded',
|
||||
color: 'blue',
|
||||
time: '2026-02-11T08:51:04.587660+07:00'
|
||||
name: "Tạo đơn hàng",
|
||||
details: "Đơn hàng được tạo",
|
||||
icon: "material-symbols:info-outline-rounded",
|
||||
color: "blue",
|
||||
time: "2026-02-11T08:51:04.587660+07:00",
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: 'Xác nhận',
|
||||
details: 'Đơn hàng được xác nhận',
|
||||
icon: 'material-symbols:check-circle-outline-rounded',
|
||||
color: 'green',
|
||||
time: '2026-02-11T10:30:04.587660+07:00'
|
||||
name: "Xác nhận",
|
||||
details: "Đơn hàng được xác nhận",
|
||||
icon: "material-symbols:check-circle-outline-rounded",
|
||||
color: "green",
|
||||
time: "2026-02-11T10:30:04.587660+07:00",
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: 'Xuất kho',
|
||||
details: 'Hàng đã xuất kho',
|
||||
icon: 'material-symbols:check-circle-outline-rounded',
|
||||
color: 'green',
|
||||
time: '2026-02-11T11:02:04.587660+07:00'
|
||||
name: "Xuất kho",
|
||||
details: "Hàng đã xuất kho",
|
||||
icon: "material-symbols:check-circle-outline-rounded",
|
||||
color: "green",
|
||||
time: "2026-02-11T11:02:04.587660+07:00",
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
name: 'Đang giao',
|
||||
details: 'Tài xế đang giao hàng',
|
||||
icon: 'material-symbols:info-outline-rounded',
|
||||
color: 'blue',
|
||||
time: '2026-02-11T14:20:04.587660+07:00'
|
||||
name: "Đang giao",
|
||||
details: "Tài xế đang giao hàng",
|
||||
icon: "material-symbols:info-outline-rounded",
|
||||
color: "blue",
|
||||
time: "2026-02-11T14:20:04.587660+07:00",
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
name: 'Giao hàng',
|
||||
details: 'Đã giao thành công',
|
||||
icon: 'material-symbols:check-circle-outline-rounded',
|
||||
color: 'green',
|
||||
time: '2026-02-11T17:38:04.587660+07:00'
|
||||
name: "Giao hàng",
|
||||
details: "Đã giao thành công",
|
||||
icon: "material-symbols:check-circle-outline-rounded",
|
||||
color: "green",
|
||||
time: "2026-02-11T17:38:04.587660+07:00",
|
||||
},
|
||||
]
|
||||
];
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<div class="is-flex is-flex-direction-column is-gap-2">
|
||||
<div
|
||||
v-for="item in historyItems"
|
||||
v-for="item in historyItems"
|
||||
:key="item.id"
|
||||
class="is-flex is-gap-2"
|
||||
>
|
||||
@@ -63,7 +63,8 @@ const historyItems = [
|
||||
:size="22"
|
||||
:class="`has-text-${item.color}-40`"
|
||||
/>
|
||||
<div class="is-flex-grow-1 has-background-grey-lighter rounded-full"
|
||||
<div
|
||||
class="is-flex-grow-1 has-background-grey-lighter rounded-full"
|
||||
style="width: 3px"
|
||||
></div>
|
||||
</div>
|
||||
@@ -73,9 +74,14 @@ const historyItems = [
|
||||
<p class="fs-15">{{ item.name }}</p>
|
||||
<p class="fs-13 has-text-grey">{{ item.details }}</p>
|
||||
</div>
|
||||
<p class="is-family-monospace fs-12 has-text-grey">{{ $dayjs(item.time).format('HH:mm') }}</p>
|
||||
<p class="is-family-monospace fs-12 has-text-grey">
|
||||
{{ $dayjs(item.time).format("HH:mm") }}
|
||||
</p>
|
||||
</div>
|
||||
<hr class="mt-4 mb-0 has-background-grey-95" style="height: 2px" />
|
||||
<hr
|
||||
class="mt-4 mb-0 has-background-grey-95"
|
||||
style="height: 2px"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,27 +1,22 @@
|
||||
<script setup>
|
||||
const props = defineProps({
|
||||
order: Object
|
||||
order: Object,
|
||||
});
|
||||
|
||||
const { $dayjs, $shortenCurrency } = useNuxtApp();
|
||||
const emit = defineEmits(['selectOrder', 'unselect']);
|
||||
const emit = defineEmits(["selectOrder", "unselect"]);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
:class="[
|
||||
'card fs-14 is-clickable',
|
||||
`has-background-${order.status__color}-95`
|
||||
]"
|
||||
<div
|
||||
:class="['card fs-14 is-clickable', `has-background-${order.status__color}-95`]"
|
||||
:style="{ border: `1px solid var(--bulma-${order.status__color}-60)` }"
|
||||
@click="selected ? emit('unselect') : emit('selectOrder', order.id)"
|
||||
>
|
||||
<div class="card-content p-4">
|
||||
<div class="mb-4 is-flex is-justify-content-space-between is-gap-1">
|
||||
<p class="fs-15 font-bold">{{ order.code }}</p>
|
||||
<span
|
||||
:class="['fs-13', `has-text-${order.payment_status__color}-40`]"
|
||||
>
|
||||
<span :class="['fs-13', `has-text-${order.payment_status__color}-40`]">
|
||||
{{ order.payment_status__name }}
|
||||
</span>
|
||||
</div>
|
||||
@@ -36,16 +31,21 @@ const emit = defineEmits(['selectOrder', 'unselect']);
|
||||
</div>
|
||||
<!-- product info -->
|
||||
<div>
|
||||
<p class="fs-24 has-text-grey-10 font-bold">{{ $shortenCurrency(order.total) }}</p>
|
||||
<p class="fs-24 has-text-grey-10 font-bold">
|
||||
{{ $shortenCurrency(order.total) }}
|
||||
</p>
|
||||
<p class="fs-13 has-text-grey">{{ order.order__products.length }} sản phẩm</p>
|
||||
</div>
|
||||
<hr class="m-0" />
|
||||
<div class="is-flex is-flex-direction-column is-gap-0.5 fs-13 has-text-grey">
|
||||
<p class=" is-flex is-align-items-center is-gap-0.5">
|
||||
<Icon name="material-symbols:calendar-today-outline-rounded" :size="16" />
|
||||
<span>{{ $dayjs(order.create_time).format('L') }}</span>
|
||||
<p class="is-flex is-align-items-center is-gap-0.5">
|
||||
<Icon
|
||||
name="material-symbols:calendar-today-outline-rounded"
|
||||
:size="16"
|
||||
/>
|
||||
<span>{{ $dayjs(order.create_time).format("L") }}</span>
|
||||
<span>•</span>
|
||||
<span>{{ $dayjs(order.create_time).format('HH:mm') }}</span>
|
||||
<span>{{ $dayjs(order.create_time).format("HH:mm") }}</span>
|
||||
</p>
|
||||
<p>
|
||||
NV: <span>{{ order.employee__name }}</span>
|
||||
@@ -55,10 +55,20 @@ const emit = defineEmits(['selectOrder', 'unselect']);
|
||||
v-if="order.status__name !== 'Hoàn thành'"
|
||||
:class="[
|
||||
'button fs-14 has-text-white',
|
||||
order.status__name === 'Nháp' ? 'is-primary' : order.status__name === 'Đã xác nhận' ? 'is-orange' : 'is-success'
|
||||
order.status__name === 'Nháp'
|
||||
? 'is-primary'
|
||||
: order.status__name === 'Đã xác nhận'
|
||||
? 'is-orange'
|
||||
: 'is-success',
|
||||
]"
|
||||
>
|
||||
{{ order.status__name === 'Nháp' ? 'Xác nhận' : order.status__name === 'Đã xác nhận' ? 'Giao hàng' : 'Hoàn thành' }}
|
||||
{{
|
||||
order.status__name === "Nháp"
|
||||
? "Xác nhận"
|
||||
: order.status__name === "Đã xác nhận"
|
||||
? "Giao hàng"
|
||||
: "Hoàn thành"
|
||||
}}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script setup>
|
||||
const props = defineProps({
|
||||
order: Object
|
||||
order: Object,
|
||||
});
|
||||
const { $numtoString } = useNuxtApp();
|
||||
</script>
|
||||
@@ -10,7 +10,9 @@ const { $numtoString } = useNuxtApp();
|
||||
<div class="is-flex is-gap-2">
|
||||
<div class="is-flex-grow-1 p-3 rounded-md has-background-grey-95">
|
||||
<p class="fs-13 has-text-grey">Tổng tiền</p>
|
||||
<p class="font-bold">{{ $numtoString(order.total, { hasUnit: true }) }}</p>
|
||||
<p class="font-bold">
|
||||
{{ $numtoString(order.total, { hasUnit: true }) }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="is-flex-grow-1 p-3 rounded-md has-background-success-95">
|
||||
<p class="fs-13 has-text-success-40">Đã thanh toán</p>
|
||||
@@ -19,7 +21,9 @@ const { $numtoString } = useNuxtApp();
|
||||
</div>
|
||||
<div class="p-4 mt-4 rounded-md has-background-danger-95">
|
||||
<p class="fs-13 has-text-danger-50">Còn lại</p>
|
||||
<p class="fs-20 font-bold has-text-danger-40">{{ $numtoString(order.total, { hasUnit: true }) }}</p>
|
||||
<p class="fs-20 font-bold has-text-danger-40">
|
||||
{{ $numtoString(order.total, { hasUnit: true }) }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -1,36 +1,36 @@
|
||||
<script setup>
|
||||
import PipelinePhase from '@/components/orders/PipelinePhase.vue';
|
||||
import PipelinePhase from "@/components/orders/PipelinePhase.vue";
|
||||
|
||||
const phases = [
|
||||
{
|
||||
name: 'Nháp',
|
||||
name: "Nháp",
|
||||
value: 2,
|
||||
icon: 'material-symbols:assignment-outline-rounded',
|
||||
color: 'yellow',
|
||||
icon: "material-symbols:assignment-outline-rounded",
|
||||
color: "yellow",
|
||||
index: 1,
|
||||
},
|
||||
{
|
||||
name: 'Đã xác nhận',
|
||||
name: "Đã xác nhận",
|
||||
value: 3,
|
||||
icon: 'material-symbols:check-circle-outline-rounded',
|
||||
color: 'blue',
|
||||
icon: "material-symbols:check-circle-outline-rounded",
|
||||
color: "blue",
|
||||
index: 2,
|
||||
},
|
||||
{
|
||||
name: 'Đang giao',
|
||||
name: "Đang giao",
|
||||
value: 2,
|
||||
icon: 'material-symbols:delivery-truck-speed-outline-rounded',
|
||||
color: 'orange',
|
||||
icon: "material-symbols:delivery-truck-speed-outline-rounded",
|
||||
color: "orange",
|
||||
index: 3,
|
||||
},
|
||||
{
|
||||
name: 'Hoàn thành',
|
||||
name: "Hoàn thành",
|
||||
value: 1,
|
||||
icon: 'material-symbols:box-outline-rounded',
|
||||
color: 'green',
|
||||
icon: "material-symbols:box-outline-rounded",
|
||||
color: "green",
|
||||
index: 4,
|
||||
},
|
||||
]
|
||||
];
|
||||
</script>
|
||||
<template>
|
||||
<div class="card">
|
||||
@@ -46,8 +46,10 @@ const phases = [
|
||||
<hr class="has-background-grey-lighter" />
|
||||
<div class="is-flex is-justify-content-space-between">
|
||||
<p>Tổng đơn hàng</p>
|
||||
<p class="fs-18 font-semibold">{{ phases.reduce((prev, curr) => prev + curr.value, 0) }}</p>
|
||||
<p class="fs-18 font-semibold">
|
||||
{{ phases.reduce((prev, curr) => prev + curr.value, 0) }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script setup>
|
||||
const props = defineProps({
|
||||
order: Object
|
||||
order: Object,
|
||||
});
|
||||
|
||||
const { $numtoString } = useNuxtApp();
|
||||
@@ -16,12 +16,17 @@ const { $numtoString } = useNuxtApp();
|
||||
>
|
||||
<div class="fs-15 is-flex is-justify-content-space-between">
|
||||
<p class="">{{ product.name }}</p>
|
||||
<p class="font-bold">{{ $numtoString(product.total, { hasUnit: true }) }}</p>
|
||||
<p class="font-bold">
|
||||
{{ $numtoString(product.total, { hasUnit: true }) }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="is-flex is-gap-8 fs-13 has-text-grey-50 mt-1">
|
||||
<p>SL: {{ product.quantity }}</p>
|
||||
<p>Đơn giá: {{ $numtoString(product.unit_price, { hasUnit: true }) }}</p>
|
||||
<p>Giảm: {{ new Intl.NumberFormat("vi-VN", { style: "percent" }).format(product.discount) }}</p>
|
||||
<p>
|
||||
Giảm:
|
||||
{{ new Intl.NumberFormat("vi-VN", { style: "percent" }).format(product.discount) }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script setup>
|
||||
const props = defineProps({
|
||||
order: Object
|
||||
order: Object,
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -10,8 +10,8 @@ const props = defineProps({
|
||||
name="material-symbols:receipt-long-outline-rounded"
|
||||
:size="50"
|
||||
class="has-text-grey-70"
|
||||
/>
|
||||
/>
|
||||
<p>Chưa có hoá đơn</p>
|
||||
<button class="button is-purple">Tạo hoá đơn</button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
<script setup>
|
||||
const props = defineProps({
|
||||
order: Object,
|
||||
selected: Boolean
|
||||
selected: Boolean,
|
||||
});
|
||||
|
||||
const { $dayjs, $shortenCurrency } = useNuxtApp();
|
||||
const emit = defineEmits(['selectOrder', 'unselect'])
|
||||
const emit = defineEmits(["selectOrder", "unselect"]);
|
||||
</script>
|
||||
<template>
|
||||
<tr
|
||||
<tr
|
||||
:class="['is-clickable', selected && 'is-selected']"
|
||||
@click="selected ? emit('unselect') : emit('selectOrder', order.id)"
|
||||
>
|
||||
@@ -22,9 +22,10 @@ const emit = defineEmits(['selectOrder', 'unselect'])
|
||||
<div>
|
||||
<p>{{ order.customer__name }}</p>
|
||||
<div class="is-flex is-gap-0.5 is-align-items-center mt-1 has-text-grey">
|
||||
<Icon name="material-symbols:call-outline-rounded"
|
||||
<Icon
|
||||
name="material-symbols:call-outline-rounded"
|
||||
:size="15"
|
||||
/>
|
||||
/>
|
||||
<span class="fs-12">{{ order.customer__phone }}</span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -36,38 +37,52 @@ const emit = defineEmits(['selectOrder', 'unselect'])
|
||||
</div>
|
||||
</td>
|
||||
<td class="has-text-centered">
|
||||
<span :class="[
|
||||
'tag rounded-full',
|
||||
`has-background-${order.status__color}-80 has-text-${order.status__color}-25`
|
||||
]">
|
||||
<span
|
||||
:class="['tag rounded-full', `has-background-${order.status__color}-80 has-text-${order.status__color}-25`]"
|
||||
>
|
||||
{{ order.status__name }}
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<p :class="`has-text-${order.payment_status__color}-40`">{{ order.payment_status__name }}</p>
|
||||
<p :class="`has-text-${order.payment_status__color}-40`">
|
||||
{{ order.payment_status__name }}
|
||||
</p>
|
||||
</td>
|
||||
<td>
|
||||
<p :class="`has-text-${order.delivery_status__color}-40`">{{ order.delivery_status__name }}</p>
|
||||
<p :class="`has-text-${order.delivery_status__color}-40`">
|
||||
{{ order.delivery_status__name }}
|
||||
</p>
|
||||
</td>
|
||||
<td>
|
||||
<div>
|
||||
<div class="is-flex is-gap-0.5">
|
||||
<Icon :size="18" name="material-symbols:calendar-month-outline-rounded" />
|
||||
<span>{{ $dayjs(order.create_time).format('L') }}</span>
|
||||
<Icon
|
||||
:size="18"
|
||||
name="material-symbols:calendar-month-outline-rounded"
|
||||
/>
|
||||
<span>{{ $dayjs(order.create_time).format("L") }}</span>
|
||||
</div>
|
||||
<p class="has-text-grey fs-12">{{ $dayjs(order.create_time).format('HH:mm') }}</p>
|
||||
<p class="has-text-grey fs-12">
|
||||
{{ $dayjs(order.create_time).format("HH:mm") }}
|
||||
</p>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<button
|
||||
v-if="order.status__name !== 'Hoàn thành'"
|
||||
:class="[
|
||||
'button fs-12 has-text-white rounded-lg',
|
||||
order.status__name === 'Nháp' ? 'is-primary' : order.status__name === 'Đã xác nhận' ? 'is-orange' : 'is-success'
|
||||
]"
|
||||
>
|
||||
{{ order.status__name === 'Nháp' ? 'Xác nhận' : order.status__name === 'Đã xác nhận' ? 'Giao hàng' : 'Hoàn thành' }}
|
||||
</button>
|
||||
v-if="order.status__name !== 'Hoàn thành'"
|
||||
:class="[
|
||||
'button fs-12 has-text-white rounded-lg',
|
||||
order.status__name === 'Nháp'
|
||||
? 'is-primary'
|
||||
: order.status__name === 'Đã xác nhận'
|
||||
? 'is-orange'
|
||||
: 'is-success',
|
||||
]"
|
||||
>
|
||||
{{
|
||||
order.status__name === "Nháp" ? "Xác nhận" : order.status__name === "Đã xác nhận" ? "Giao hàng" : "Hoàn thành"
|
||||
}}
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
</template>
|
||||
@@ -80,4 +95,4 @@ td {
|
||||
vertical-align: middle;
|
||||
--bulma-table-cell-padding: 0.75em;
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
||||
@@ -1,48 +1,48 @@
|
||||
<script setup>
|
||||
import OrderHighlightCard from '@/components/orders/OrderHighlightCard.vue';
|
||||
import OrderPipeline from '@/components/orders/OrderPipeline.vue';
|
||||
import OrdersTable from '@/components/orders/OrdersTable.vue';
|
||||
import OrderHighlightCard from "@/components/orders/OrderHighlightCard.vue";
|
||||
import OrderPipeline from "@/components/orders/OrderPipeline.vue";
|
||||
import OrdersTable from "@/components/orders/OrdersTable.vue";
|
||||
|
||||
const { $store } = useNuxtApp();
|
||||
const highlights = [
|
||||
{
|
||||
name: 'Nháp',
|
||||
name: "Nháp",
|
||||
value: 2,
|
||||
icon: 'material-symbols:assignment-outline-rounded',
|
||||
color: 'yellow',
|
||||
icon: "material-symbols:assignment-outline-rounded",
|
||||
color: "yellow",
|
||||
},
|
||||
{
|
||||
name: 'Đã xác nhận',
|
||||
name: "Đã xác nhận",
|
||||
value: 3,
|
||||
icon: 'material-symbols:check-circle-outline-rounded',
|
||||
color: 'blue',
|
||||
icon: "material-symbols:check-circle-outline-rounded",
|
||||
color: "blue",
|
||||
},
|
||||
{
|
||||
name: 'Đang giao',
|
||||
name: "Đang giao",
|
||||
value: 2,
|
||||
icon: 'material-symbols:delivery-truck-speed-outline-rounded',
|
||||
color: 'orange',
|
||||
icon: "material-symbols:delivery-truck-speed-outline-rounded",
|
||||
color: "orange",
|
||||
},
|
||||
{
|
||||
name: 'Hoàn thành',
|
||||
name: "Hoàn thành",
|
||||
value: 1,
|
||||
icon: 'material-symbols:box-outline-rounded',
|
||||
color: 'green',
|
||||
icon: "material-symbols:box-outline-rounded",
|
||||
color: "green",
|
||||
},
|
||||
{
|
||||
name: 'Doanh thu',
|
||||
value: '6.8M',
|
||||
icon: 'material-symbols:attach-money-rounded',
|
||||
color: 'purple',
|
||||
unit: 'VNĐ'
|
||||
name: "Doanh thu",
|
||||
value: "6.8M",
|
||||
icon: "material-symbols:attach-money-rounded",
|
||||
color: "purple",
|
||||
unit: "VNĐ",
|
||||
},
|
||||
];
|
||||
|
||||
const viewModes = [
|
||||
{ name: 'list', icon: 'material-symbols:format-list-bulleted-rounded' },
|
||||
{ name: 'grid', icon: 'material-symbols:grid-view-outline-rounded' }
|
||||
{ name: "list", icon: "material-symbols:format-list-bulleted-rounded" },
|
||||
{ name: "grid", icon: "material-symbols:grid-view-outline-rounded" },
|
||||
];
|
||||
const viewMode = ref('list');
|
||||
const viewMode = ref("list");
|
||||
</script>
|
||||
<template>
|
||||
<div>
|
||||
@@ -50,7 +50,7 @@ const viewMode = ref('list');
|
||||
defer
|
||||
to="#header-right-slot"
|
||||
v-if="$store.tabinfo.tab.code === 'orders'"
|
||||
>
|
||||
>
|
||||
<div class="is-flex is-gap-2 is-justify-content-flex-end is-align-items-center">
|
||||
<div class="tabs is-toggle m-0">
|
||||
<ul class="is-flex-grow-0 ml-auto">
|
||||
@@ -62,7 +62,10 @@ const viewMode = ref('list');
|
||||
>
|
||||
<a class="px-3 py-1">
|
||||
<span class="icon m-0">
|
||||
<Icon :name="mode.icon" :size="18" />
|
||||
<Icon
|
||||
:name="mode.icon"
|
||||
:size="18"
|
||||
/>
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
@@ -70,7 +73,10 @@ const viewMode = ref('list');
|
||||
</div>
|
||||
<button class="button fs-14 is-primary">
|
||||
<span class="icon">
|
||||
<Icon :size="18" name="material-symbols:add-2-rounded" />
|
||||
<Icon
|
||||
:size="18"
|
||||
name="material-symbols:add-2-rounded"
|
||||
/>
|
||||
</span>
|
||||
<span>Tạo đơn hàng</span>
|
||||
</button>
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
<script setup>
|
||||
import OrderKanbanCard from '@/components/orders/OrderKanbanCard.vue';
|
||||
import OrderKanbanCard from "@/components/orders/OrderKanbanCard.vue";
|
||||
|
||||
const props = defineProps({
|
||||
orders: Array,
|
||||
statuses: Array,
|
||||
});
|
||||
|
||||
const emit = defineEmits(['selectOrder', 'unselect']);
|
||||
const emit = defineEmits(["selectOrder", "unselect"]);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -19,30 +19,39 @@ const emit = defineEmits(['selectOrder', 'unselect']);
|
||||
style="border: none"
|
||||
>
|
||||
<div class="card-content p-0 is-clipped">
|
||||
<div :class="['p-4 is-flex is-justify-content-space-between is-align-items-center', `has-background-${status.color}-90`]">
|
||||
<div
|
||||
:class="[
|
||||
'p-4 is-flex is-justify-content-space-between is-align-items-center',
|
||||
`has-background-${status.color}-90`,
|
||||
]"
|
||||
>
|
||||
<p class="font-semibold has-text-grey-10">{{ status.name }}</p>
|
||||
<p class="px-2 py-1 font-semibold rounded-lg has-background-white"
|
||||
:style="{ border: `1px solid var(--bulma-${status.color}-60)`}"
|
||||
<p
|
||||
class="px-2 py-1 font-semibold rounded-lg has-background-white"
|
||||
:style="{ border: `1px solid var(--bulma-${status.color}-60)` }"
|
||||
>
|
||||
{{ orders.filter(o => o.status === status.id).length }}
|
||||
{{ orders.filter((o) => o.status === status.id).length }}
|
||||
</p>
|
||||
</div>
|
||||
<hr class="m-0 has-background-grey-80" />
|
||||
<div class="has-background-grey-95 p-4">
|
||||
<OrderKanbanCard
|
||||
v-if="orders.filter(o => o.status === status.id).length > 0"
|
||||
v-for="order in orders.filter(o => o.status === status.id)"
|
||||
<OrderKanbanCard
|
||||
v-if="orders.filter((o) => o.status === status.id).length > 0"
|
||||
v-for="order in orders.filter((o) => o.status === status.id)"
|
||||
:key="order.id"
|
||||
:order="order"
|
||||
@selectOrder="emit('selectOrder', order.id)"
|
||||
@unselect="emit('unselect')"
|
||||
/>
|
||||
<p v-else class="fs-13 has-text-centered has-text-grey">
|
||||
<p
|
||||
v-else
|
||||
class="fs-13 has-text-centered has-text-grey"
|
||||
>
|
||||
Không có đơn hàng
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -1,428 +1,428 @@
|
||||
<script setup>
|
||||
import OrderRow from '@/components/orders/OrderRow.vue';
|
||||
import SelectedOrder from '@/components/orders/SelectedOrder.vue';
|
||||
import { pull } from 'es-toolkit';
|
||||
import OrderRow from "@/components/orders/OrderRow.vue";
|
||||
import SelectedOrder from "@/components/orders/SelectedOrder.vue";
|
||||
import { pull } from "es-toolkit";
|
||||
|
||||
const props = defineProps({
|
||||
viewMode: String
|
||||
viewMode: String,
|
||||
});
|
||||
|
||||
const { $dayjs } = useNuxtApp();
|
||||
|
||||
const orders = [
|
||||
{
|
||||
{
|
||||
id: 1,
|
||||
code: 'SO001',
|
||||
code: "SO001",
|
||||
employee: 1,
|
||||
employee__name: 'Trần Thị B',
|
||||
employee__name: "Trần Thị B",
|
||||
customer: 1,
|
||||
customer__name: 'Nguyễn Văn A',
|
||||
customer__phone: '0901234567',
|
||||
total: '5200000.00',
|
||||
customer__name: "Nguyễn Văn A",
|
||||
customer__phone: "0901234567",
|
||||
total: "5200000.00",
|
||||
status: 1,
|
||||
status__name: 'Nháp',
|
||||
status__color: 'yellow',
|
||||
status__name: "Nháp",
|
||||
status__color: "yellow",
|
||||
payment_status: 1,
|
||||
payment_status__name: 'Chưa thanh toán',
|
||||
payment_status__color: 'red',
|
||||
payment_status__name: "Chưa thanh toán",
|
||||
payment_status__color: "red",
|
||||
delivery_status: 1,
|
||||
delivery_status__name: 'Chờ xử lý',
|
||||
delivery_status__color: 'grey',
|
||||
delivery_status__name: "Chờ xử lý",
|
||||
delivery_status__color: "grey",
|
||||
order__products: [
|
||||
{
|
||||
id: 1,
|
||||
name: 'Kem chống nắng SPF 50+',
|
||||
unit_price: '280000.00',
|
||||
name: "Kem chống nắng SPF 50+",
|
||||
unit_price: "280000.00",
|
||||
quantity: 10,
|
||||
discount: null,
|
||||
total: '2800000.00'
|
||||
total: "2800000.00",
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: 'Serum Vitamin C 30ml',
|
||||
unit_price: '450000.00',
|
||||
name: "Serum Vitamin C 30ml",
|
||||
unit_price: "450000.00",
|
||||
quantity: 5,
|
||||
discount: 0.1,
|
||||
total: '2025000.00'
|
||||
total: "2025000.00",
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: 'Son dưỡng môi vitamin E',
|
||||
unit_price: '75000.00',
|
||||
name: "Son dưỡng môi vitamin E",
|
||||
unit_price: "75000.00",
|
||||
quantity: 5,
|
||||
discount: null,
|
||||
total: '375000.00'
|
||||
total: "375000.00",
|
||||
},
|
||||
],
|
||||
create_time: '2026-02-11T08:51:04.587660+07:00'
|
||||
create_time: "2026-02-11T08:51:04.587660+07:00",
|
||||
},
|
||||
{
|
||||
{
|
||||
id: 2,
|
||||
code: 'SO002',
|
||||
code: "SO002",
|
||||
employee: 1,
|
||||
employee__name: 'Trần Thị B',
|
||||
employee__name: "Trần Thị B",
|
||||
customer: 3,
|
||||
customer__name: 'Lê Thị C',
|
||||
customer__phone: '0912345678',
|
||||
total: '8500000.00',
|
||||
customer__name: "Lê Thị C",
|
||||
customer__phone: "0912345678",
|
||||
total: "8500000.00",
|
||||
status: 2,
|
||||
status__name: 'Đã xác nhận',
|
||||
status__color: 'blue',
|
||||
status__name: "Đã xác nhận",
|
||||
status__color: "blue",
|
||||
payment_status: 2,
|
||||
payment_status__name: 'Một phần',
|
||||
payment_status__color: 'yellow',
|
||||
payment_status__name: "Một phần",
|
||||
payment_status__color: "yellow",
|
||||
delivery_status: 2,
|
||||
delivery_status__name: 'Sẵn sàng',
|
||||
delivery_status__color: 'blue',
|
||||
delivery_status__name: "Sẵn sàng",
|
||||
delivery_status__color: "blue",
|
||||
order__products: [
|
||||
{
|
||||
id: 3,
|
||||
name: 'Mặt nạ collagen 10 miếng',
|
||||
unit_price: '320000.00',
|
||||
name: "Mặt nạ collagen 10 miếng",
|
||||
unit_price: "320000.00",
|
||||
quantity: 15,
|
||||
discount: 0.05,
|
||||
total: '4560000.00'
|
||||
total: "4560000.00",
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
name: 'Toner cân bằng da 200ml',
|
||||
unit_price: '180000.00',
|
||||
name: "Toner cân bằng da 200ml",
|
||||
unit_price: "180000.00",
|
||||
quantity: 20,
|
||||
discount: 0.1,
|
||||
total: '3240000.00'
|
||||
total: "3240000.00",
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
name: 'Gel rửa mặt làm sạch sâu',
|
||||
unit_price: '140000.00',
|
||||
name: "Gel rửa mặt làm sạch sâu",
|
||||
unit_price: "140000.00",
|
||||
quantity: 5,
|
||||
discount: null,
|
||||
total: '700000.00'
|
||||
total: "700000.00",
|
||||
},
|
||||
],
|
||||
create_time: '2026-04-06T09:10:09.587660+07:00'
|
||||
create_time: "2026-04-06T09:10:09.587660+07:00",
|
||||
},
|
||||
{
|
||||
{
|
||||
id: 3,
|
||||
code: 'SO003',
|
||||
code: "SO003",
|
||||
employee: 5,
|
||||
employee__name: 'Hoàng Văn E',
|
||||
employee__name: "Hoàng Văn E",
|
||||
customer: 4,
|
||||
customer__name: 'Phạm Văn D',
|
||||
customer__phone: '0923456703',
|
||||
total: '12300000.00',
|
||||
customer__name: "Phạm Văn D",
|
||||
customer__phone: "0923456703",
|
||||
total: "12300000.00",
|
||||
status: 3,
|
||||
status__name: 'Đang giao',
|
||||
status__color: 'orange',
|
||||
status__name: "Đang giao",
|
||||
status__color: "orange",
|
||||
payment_status: 3,
|
||||
payment_status__name: 'Đã thanh toán',
|
||||
payment_status__color: 'green',
|
||||
payment_status__name: "Đã thanh toán",
|
||||
payment_status__color: "green",
|
||||
delivery_status: 3,
|
||||
delivery_status__name: 'Hoàn thành',
|
||||
delivery_status__color: 'green',
|
||||
delivery_status__name: "Hoàn thành",
|
||||
delivery_status__color: "green",
|
||||
order__products: [
|
||||
{
|
||||
id: 6,
|
||||
name: 'Kem dưỡng ẩm ban đêm',
|
||||
unit_price: '380000.00',
|
||||
name: "Kem dưỡng ẩm ban đêm",
|
||||
unit_price: "380000.00",
|
||||
quantity: 20,
|
||||
discount: 0.05,
|
||||
total: '7220000.00'
|
||||
total: "7220000.00",
|
||||
},
|
||||
{
|
||||
id: 7,
|
||||
name: 'Phấn nền BB cream',
|
||||
unit_price: '220000.00',
|
||||
name: "Phấn nền BB cream",
|
||||
unit_price: "220000.00",
|
||||
quantity: 15,
|
||||
discount: null,
|
||||
total: '3300000.00'
|
||||
total: "3300000.00",
|
||||
},
|
||||
{
|
||||
id: 8,
|
||||
name: 'Nước tẩy trang 3 trong 1',
|
||||
unit_price: '195000.00',
|
||||
name: "Nước tẩy trang 3 trong 1",
|
||||
unit_price: "195000.00",
|
||||
quantity: 10,
|
||||
discount: 0.1,
|
||||
total: '1755000.00'
|
||||
total: "1755000.00",
|
||||
},
|
||||
],
|
||||
create_time: '2026-04-05T02:33:24.587660+07:00'
|
||||
create_time: "2026-04-05T02:33:24.587660+07:00",
|
||||
},
|
||||
{
|
||||
{
|
||||
id: 4,
|
||||
code: 'SO004',
|
||||
code: "SO004",
|
||||
employee: 1,
|
||||
employee__name: 'Trần Thị B',
|
||||
employee__name: "Trần Thị B",
|
||||
customer: 6,
|
||||
customer__name: 'Vũ Thị F',
|
||||
customer__phone: '0934835222',
|
||||
total: '6800000.00',
|
||||
customer__name: "Vũ Thị F",
|
||||
customer__phone: "0934835222",
|
||||
total: "6800000.00",
|
||||
status: 4,
|
||||
status__name: 'Hoàn thành',
|
||||
status__color: 'green',
|
||||
status__name: "Hoàn thành",
|
||||
status__color: "green",
|
||||
payment_status: 3,
|
||||
payment_status__name: 'Đã thanh toán',
|
||||
payment_status__color: 'green',
|
||||
payment_status__name: "Đã thanh toán",
|
||||
payment_status__color: "green",
|
||||
delivery_status: 3,
|
||||
delivery_status__name: 'Hoàn thành',
|
||||
delivery_status__color: 'green',
|
||||
delivery_status__name: "Hoàn thành",
|
||||
delivery_status__color: "green",
|
||||
order__products: [
|
||||
{
|
||||
id: 9,
|
||||
name: 'Dầu gội thảo mộc 500ml',
|
||||
unit_price: '120000.00',
|
||||
name: "Dầu gội thảo mộc 500ml",
|
||||
unit_price: "120000.00",
|
||||
quantity: 30,
|
||||
discount: 0.1,
|
||||
total: '3240000.00'
|
||||
total: "3240000.00",
|
||||
},
|
||||
{
|
||||
id: 10,
|
||||
name: 'Sữa rửa mặt trà xanh 150ml',
|
||||
unit_price: '150000.00',
|
||||
name: "Sữa rửa mặt trà xanh 150ml",
|
||||
unit_price: "150000.00",
|
||||
quantity: 20,
|
||||
discount: 0.05,
|
||||
total: '2850000.00'
|
||||
total: "2850000.00",
|
||||
},
|
||||
{
|
||||
id: 11,
|
||||
name: 'Son dưỡng môi vitamin E',
|
||||
unit_price: '75000.00',
|
||||
name: "Son dưỡng môi vitamin E",
|
||||
unit_price: "75000.00",
|
||||
quantity: 10,
|
||||
discount: 0.05,
|
||||
total: '712500.00'
|
||||
total: "712500.00",
|
||||
},
|
||||
],
|
||||
create_time: '2026-04-04T23:21:11.587660+07:00'
|
||||
create_time: "2026-04-04T23:21:11.587660+07:00",
|
||||
},
|
||||
{
|
||||
{
|
||||
id: 5,
|
||||
code: 'SO005',
|
||||
code: "SO005",
|
||||
employee: 5,
|
||||
employee__name: 'Hoàng Văn E',
|
||||
employee__name: "Hoàng Văn E",
|
||||
customer: 7,
|
||||
customer__name: 'Đỗ Văn G',
|
||||
customer__phone: '0945781113',
|
||||
total: '9400000.00',
|
||||
customer__name: "Đỗ Văn G",
|
||||
customer__phone: "0945781113",
|
||||
total: "9400000.00",
|
||||
status: 2,
|
||||
status__name: 'Đã xác nhận',
|
||||
status__color: 'blue',
|
||||
status__name: "Đã xác nhận",
|
||||
status__color: "blue",
|
||||
payment_status: 1,
|
||||
payment_status__name: 'Chưa thanh toán',
|
||||
payment_status__color: 'red',
|
||||
payment_status__name: "Chưa thanh toán",
|
||||
payment_status__color: "red",
|
||||
delivery_status: 1,
|
||||
delivery_status__name: 'Chờ xử lý',
|
||||
delivery_status__color: 'grey',
|
||||
delivery_status__name: "Chờ xử lý",
|
||||
delivery_status__color: "grey",
|
||||
order__products: [
|
||||
{
|
||||
id: 12,
|
||||
name: 'Kem mắt chống lão hóa',
|
||||
unit_price: '550000.00',
|
||||
name: "Kem mắt chống lão hóa",
|
||||
unit_price: "550000.00",
|
||||
quantity: 10,
|
||||
discount: null,
|
||||
total: '5500000.00'
|
||||
total: "5500000.00",
|
||||
},
|
||||
{
|
||||
id: 13,
|
||||
name: 'Serum Vitamin C 30ml',
|
||||
unit_price: '450000.00',
|
||||
name: "Serum Vitamin C 30ml",
|
||||
unit_price: "450000.00",
|
||||
quantity: 8,
|
||||
discount: 0.05,
|
||||
total: '3420000.00'
|
||||
total: "3420000.00",
|
||||
},
|
||||
{
|
||||
id: 14,
|
||||
name: 'Gel rửa mặt làm sạch sâu',
|
||||
unit_price: '140000.00',
|
||||
name: "Gel rửa mặt làm sạch sâu",
|
||||
unit_price: "140000.00",
|
||||
quantity: 5,
|
||||
discount: 0.15,
|
||||
total: '595000.00'
|
||||
total: "595000.00",
|
||||
},
|
||||
],
|
||||
create_time: '2026-04-07T11:21:46.587660+07:00'
|
||||
create_time: "2026-04-07T11:21:46.587660+07:00",
|
||||
},
|
||||
{
|
||||
{
|
||||
id: 6,
|
||||
code: 'SO006',
|
||||
code: "SO006",
|
||||
employee: 1,
|
||||
employee__name: 'Trần Thị B',
|
||||
employee__name: "Trần Thị B",
|
||||
customer: 8,
|
||||
customer__name: 'Bùi Thị H',
|
||||
customer__phone: '0933184392',
|
||||
total: '4200000.00',
|
||||
customer__name: "Bùi Thị H",
|
||||
customer__phone: "0933184392",
|
||||
total: "4200000.00",
|
||||
status: 1,
|
||||
status__name: 'Nháp',
|
||||
status__color: 'yellow',
|
||||
status__name: "Nháp",
|
||||
status__color: "yellow",
|
||||
payment_status: 1,
|
||||
payment_status__name: 'Chưa thanh toán',
|
||||
payment_status__color: 'red',
|
||||
payment_status__name: "Chưa thanh toán",
|
||||
payment_status__color: "red",
|
||||
delivery_status: 1,
|
||||
delivery_status__name: 'Chờ xử lý',
|
||||
delivery_status__color: 'grey',
|
||||
delivery_status__name: "Chờ xử lý",
|
||||
delivery_status__color: "grey",
|
||||
order__products: [
|
||||
{
|
||||
id: 15,
|
||||
name: 'Toner cân bằng da 200ml',
|
||||
unit_price: '180000.00',
|
||||
name: "Toner cân bằng da 200ml",
|
||||
unit_price: "180000.00",
|
||||
quantity: 15,
|
||||
discount: null,
|
||||
total: '2700000.00'
|
||||
total: "2700000.00",
|
||||
},
|
||||
{
|
||||
id: 16,
|
||||
name: 'Mặt nạ collagen 10 miếng',
|
||||
unit_price: '320000.00',
|
||||
name: "Mặt nạ collagen 10 miếng",
|
||||
unit_price: "320000.00",
|
||||
quantity: 5,
|
||||
discount: 0.05,
|
||||
total: '1520000.00'
|
||||
total: "1520000.00",
|
||||
},
|
||||
],
|
||||
create_time: '2026-04-07T13:17:36.587660+07:00'
|
||||
create_time: "2026-04-07T13:17:36.587660+07:00",
|
||||
},
|
||||
{
|
||||
{
|
||||
id: 7,
|
||||
code: 'SO007',
|
||||
code: "SO007",
|
||||
employee: 5,
|
||||
employee__name: 'Hoàng Văn E',
|
||||
employee__name: "Hoàng Văn E",
|
||||
customer: 9,
|
||||
customer__name: 'Ngô Văn I',
|
||||
customer__phone: '0978335172',
|
||||
total: '15600000.00',
|
||||
customer__name: "Ngô Văn I",
|
||||
customer__phone: "0978335172",
|
||||
total: "15600000.00",
|
||||
status: 3,
|
||||
status__name: 'Đang giao',
|
||||
status__color: 'orange',
|
||||
status__name: "Đang giao",
|
||||
status__color: "orange",
|
||||
payment_status: 3,
|
||||
payment_status__name: 'Đã thanh toán',
|
||||
payment_status__color: 'green',
|
||||
payment_status__name: "Đã thanh toán",
|
||||
payment_status__color: "green",
|
||||
delivery_status: 2,
|
||||
delivery_status__name: 'Hoàn thành',
|
||||
delivery_status__color: 'green',
|
||||
delivery_status__name: "Hoàn thành",
|
||||
delivery_status__color: "green",
|
||||
order__products: [
|
||||
{
|
||||
id: 17,
|
||||
name: 'Kem chống nắng SPF 50+',
|
||||
unit_price: '280000.00',
|
||||
name: "Kem chống nắng SPF 50+",
|
||||
unit_price: "280000.00",
|
||||
quantity: 30,
|
||||
discount: 0.1,
|
||||
total: '7560000.00'
|
||||
total: "7560000.00",
|
||||
},
|
||||
{
|
||||
id: 18,
|
||||
name: 'Phấn nền BB cream',
|
||||
unit_price: '220000.00',
|
||||
name: "Phấn nền BB cream",
|
||||
unit_price: "220000.00",
|
||||
quantity: 25,
|
||||
discount: 0.05,
|
||||
total: '5225000.00'
|
||||
total: "5225000.00",
|
||||
},
|
||||
{
|
||||
id: 19,
|
||||
name: 'Kem dưỡng ẩm ban đêm',
|
||||
unit_price: '380000.00',
|
||||
name: "Kem dưỡng ẩm ban đêm",
|
||||
unit_price: "380000.00",
|
||||
quantity: 8,
|
||||
discount: 0.05,
|
||||
total: '2880000.00'
|
||||
total: "2880000.00",
|
||||
},
|
||||
],
|
||||
create_time: '2026-06-04T09:30:12.587660+07:00'
|
||||
create_time: "2026-06-04T09:30:12.587660+07:00",
|
||||
},
|
||||
{
|
||||
{
|
||||
id: 8,
|
||||
code: 'SO008',
|
||||
code: "SO008",
|
||||
employee: 1,
|
||||
employee__name: 'Trần Thị B',
|
||||
employee__name: "Trần Thị B",
|
||||
customer: 11,
|
||||
customer__name: 'Đinh Thị K',
|
||||
customer__phone: '0922104853',
|
||||
total: '7900000.00',
|
||||
customer__name: "Đinh Thị K",
|
||||
customer__phone: "0922104853",
|
||||
total: "7900000.00",
|
||||
status: 2,
|
||||
status__name: 'Đã xác nhận',
|
||||
status__color: 'blue',
|
||||
status__name: "Đã xác nhận",
|
||||
status__color: "blue",
|
||||
payment_status: 2,
|
||||
payment_status__name: 'Một phần',
|
||||
payment_status__color: 'yellow',
|
||||
payment_status__name: "Một phần",
|
||||
payment_status__color: "yellow",
|
||||
delivery_status: 2,
|
||||
delivery_status__name: 'Sẵn sàng',
|
||||
delivery_status__color: 'blue',
|
||||
delivery_status__name: "Sẵn sàng",
|
||||
delivery_status__color: "blue",
|
||||
order__products: [
|
||||
{
|
||||
id: 20,
|
||||
name: 'Nước tẩy trang 3 trong 1',
|
||||
unit_price: '195000.00',
|
||||
name: "Nước tẩy trang 3 trong 1",
|
||||
unit_price: "195000.00",
|
||||
quantity: 20,
|
||||
discount: 0.05,
|
||||
total: '3705000.00'
|
||||
total: "3705000.00",
|
||||
},
|
||||
{
|
||||
id: 21,
|
||||
name: 'Sữa rửa mặt trà xanh 150ml',
|
||||
unit_price: '150000.00',
|
||||
name: "Sữa rửa mặt trà xanh 150ml",
|
||||
unit_price: "150000.00",
|
||||
quantity: 18,
|
||||
discount: null,
|
||||
total: '2700000.00'
|
||||
total: "2700000.00",
|
||||
},
|
||||
{
|
||||
id: 22,
|
||||
name: 'Dầu gội thảo mộc 500ml',
|
||||
unit_price: '120000.00',
|
||||
name: "Dầu gội thảo mộc 500ml",
|
||||
unit_price: "120000.00",
|
||||
quantity: 13,
|
||||
discount: 0.05,
|
||||
total: '1482000.00'
|
||||
total: "1482000.00",
|
||||
},
|
||||
],
|
||||
create_time: '2026-04-06T16:01:22.587660+07:00'
|
||||
create_time: "2026-04-06T16:01:22.587660+07:00",
|
||||
},
|
||||
];
|
||||
|
||||
const statuses = [
|
||||
{
|
||||
id: 1,
|
||||
name: 'Nháp',
|
||||
color: 'yellow',
|
||||
name: "Nháp",
|
||||
color: "yellow",
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: 'Đã xác nhận',
|
||||
color: 'blue',
|
||||
name: "Đã xác nhận",
|
||||
color: "blue",
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: 'Đang giao',
|
||||
color: 'orange',
|
||||
name: "Đang giao",
|
||||
color: "orange",
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
name: 'Hoàn thành',
|
||||
color: 'green',
|
||||
name: "Hoàn thành",
|
||||
color: "green",
|
||||
},
|
||||
];
|
||||
|
||||
const paymentStatuses = [
|
||||
{
|
||||
id: 1,
|
||||
name: 'Chưa thanh toán',
|
||||
color: 'red',
|
||||
name: "Chưa thanh toán",
|
||||
color: "red",
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: 'Một phần',
|
||||
color: 'yellow',
|
||||
name: "Một phần",
|
||||
color: "yellow",
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: 'Đã thanh toán',
|
||||
color: 'green',
|
||||
}
|
||||
name: "Đã thanh toán",
|
||||
color: "green",
|
||||
},
|
||||
];
|
||||
|
||||
const employees = [
|
||||
{
|
||||
id: 1,
|
||||
name: 'Trần Thị B',
|
||||
name: "Trần Thị B",
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
name: 'Hoàng Văn E',
|
||||
name: "Hoàng Văn E",
|
||||
},
|
||||
]
|
||||
];
|
||||
|
||||
const input = ref();
|
||||
const dateRange = ref({
|
||||
@@ -435,35 +435,35 @@ const selectedPaymentStatus = ref();
|
||||
const selectedEmployee = ref();
|
||||
|
||||
const filteredOrders = computed(() => {
|
||||
const filteredByInput = orders.filter(order => {
|
||||
const filteredByInput = orders.filter((order) => {
|
||||
if (!input.value) return true;
|
||||
const values = Object.values(order);
|
||||
const strValues = values.filter(v => typeof v === 'string');
|
||||
return strValues.some(str => str.toLowerCase().includes(input.value.toLowerCase()));
|
||||
const strValues = values.filter((v) => typeof v === "string");
|
||||
return strValues.some((str) => str.toLowerCase().includes(input.value.toLowerCase()));
|
||||
});
|
||||
|
||||
const filteredByStatuses = filteredByInput.filter(order => {
|
||||
const filteredByStatuses = filteredByInput.filter((order) => {
|
||||
if (selectedStatuses.value.length === 0) return true;
|
||||
return selectedStatuses.value.includes(order.status);
|
||||
});
|
||||
|
||||
const filteredByPaymentStatuses = filteredByStatuses.filter(order => {
|
||||
const filteredByPaymentStatuses = filteredByStatuses.filter((order) => {
|
||||
if (!selectedPaymentStatus.value) return true;
|
||||
return order.payment_status === selectedPaymentStatus.value;
|
||||
});
|
||||
|
||||
const filteredByEmployees = filteredByPaymentStatuses.filter(order => {
|
||||
const filteredByEmployees = filteredByPaymentStatuses.filter((order) => {
|
||||
if (!selectedEmployee.value) return true;
|
||||
return order.employee === selectedEmployee.value;
|
||||
});
|
||||
|
||||
const filteredByDates = filteredByEmployees.filter(order => {
|
||||
const filteredByDates = filteredByEmployees.filter((order) => {
|
||||
if (!dateRange.value) return true;
|
||||
const from = $dayjs(dateRange.value.from || 0);
|
||||
const to = $dayjs(dateRange.value.to || undefined);
|
||||
const createTime = $dayjs(order.create_time);
|
||||
return createTime.isSameOrAfter(from) && createTime.isSameOrBefore(to);
|
||||
})
|
||||
});
|
||||
|
||||
return filteredByDates;
|
||||
});
|
||||
@@ -476,7 +476,7 @@ watch(filteredOrders, () => {
|
||||
|
||||
function toggleStatus(id) {
|
||||
if (selectedStatuses.value.includes(id)) {
|
||||
selectedStatuses.value = pull(selectedStatuses.value, [id])
|
||||
selectedStatuses.value = pull(selectedStatuses.value, [id]);
|
||||
} else {
|
||||
selectedStatuses.value.push(id);
|
||||
}
|
||||
@@ -489,49 +489,61 @@ function toggleStatus(id) {
|
||||
<div class="is-flex is-gap-2 is-align-items-center">
|
||||
<div class="field is-flex-grow-1 m-0">
|
||||
<p class="control has-icons-left">
|
||||
<input v-model="input" class="input" type="text" placeholder="Tìm kiếm mã đơn, khách hàng..." />
|
||||
<input
|
||||
v-model="input"
|
||||
class="input"
|
||||
type="text"
|
||||
placeholder="Tìm kiếm mã đơn, khách hàng..."
|
||||
/>
|
||||
<span class="icon is-small is-left">
|
||||
<Icon name="material-symbols:search-rounded" :size="24" />
|
||||
<Icon
|
||||
name="material-symbols:search-rounded"
|
||||
:size="24"
|
||||
/>
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
<div class="is-flex is-gap-1 is-align-items-center">
|
||||
<!-- Date pickers -->
|
||||
<Datepicker v-bind="{
|
||||
record: dateRange,
|
||||
attr: 'from',
|
||||
maxdate: new Date(),
|
||||
onDate: (e) => dateRange.from = e
|
||||
}" />
|
||||
<Datepicker
|
||||
v-bind="{
|
||||
record: dateRange,
|
||||
attr: 'from',
|
||||
maxdate: new Date(),
|
||||
onDate: (e) => (dateRange.from = e),
|
||||
}"
|
||||
/>
|
||||
<span>–</span>
|
||||
<Datepicker v-bind="{
|
||||
record: dateRange,
|
||||
attr: 'to',
|
||||
maxdate: new Date(),
|
||||
onDate: (e) => dateRange.to = e
|
||||
}" />
|
||||
<Datepicker
|
||||
v-bind="{
|
||||
record: dateRange,
|
||||
attr: 'to',
|
||||
maxdate: new Date(),
|
||||
onDate: (e) => (dateRange.to = e),
|
||||
}"
|
||||
/>
|
||||
</div>
|
||||
<div class="select">
|
||||
<select v-model="selectedPaymentStatus">
|
||||
<option :value="undefined">Phương thức thanh toán</option>
|
||||
<option
|
||||
<option
|
||||
v-for="paymentStatus in paymentStatuses"
|
||||
:key="paymentStatus.id"
|
||||
:value="paymentStatus.id"
|
||||
>
|
||||
{{ paymentStatus.name }}
|
||||
{{ paymentStatus.name }}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="select">
|
||||
<select v-model="selectedEmployee">
|
||||
<option :value="undefined">Nhân viên</option>
|
||||
<option
|
||||
<option
|
||||
v-for="employee in employees"
|
||||
:key="employee.id"
|
||||
:value="employee.id"
|
||||
>
|
||||
{{ employee.name }}
|
||||
{{ employee.name }}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
@@ -542,13 +554,13 @@ function toggleStatus(id) {
|
||||
:key="status.id"
|
||||
:class="[
|
||||
'tag fs-13 is-rounded',
|
||||
selectedStatuses.includes(status.id) && `has-background-${status.color}-80`
|
||||
selectedStatuses.includes(status.id) && `has-background-${status.color}-80`,
|
||||
]"
|
||||
@click="toggleStatus(status.id)"
|
||||
>
|
||||
{{ status.name }}
|
||||
<Icon
|
||||
v-if="selectedStatuses.includes(status.id)"
|
||||
v-if="selectedStatuses.includes(status.id)"
|
||||
name="material-symbols:check-rounded"
|
||||
:size="18"
|
||||
class="ml-1"
|
||||
@@ -564,7 +576,10 @@ function toggleStatus(id) {
|
||||
<div class="card-content p-0">
|
||||
<template v-if="viewMode === 'list'">
|
||||
<p class="p-5 fs-17 font-semibold is-flex is-align-items-center is-gap-1">
|
||||
<Icon name="material-symbols:list-alt-outline-rounded" :size="22" />
|
||||
<Icon
|
||||
name="material-symbols:list-alt-outline-rounded"
|
||||
:size="22"
|
||||
/>
|
||||
<span>Danh sách đơn hàng ({{ filteredOrders.length }})</span>
|
||||
</p>
|
||||
<table class="table is-fullwidth is-hoverable fs-13">
|
||||
@@ -584,10 +599,15 @@ function toggleStatus(id) {
|
||||
<OrderRow
|
||||
v-for="order in filteredOrders"
|
||||
:key="order.id"
|
||||
v-bind="{ order, selected: order.id === selectedOrder?.id }"
|
||||
@selectOrder="(id) => {
|
||||
selectedOrder = filteredOrders.find(order => order.id === id);
|
||||
v-bind="{
|
||||
order,
|
||||
selected: order.id === selectedOrder?.id,
|
||||
}"
|
||||
@selectOrder="
|
||||
(id) => {
|
||||
selectedOrder = filteredOrders.find((order) => order.id === id);
|
||||
}
|
||||
"
|
||||
@unselect="selectedOrder = null"
|
||||
/>
|
||||
</tbody>
|
||||
@@ -597,15 +617,20 @@ function toggleStatus(id) {
|
||||
v-else
|
||||
:orders="filteredOrders"
|
||||
:statuses="statuses"
|
||||
@selectOrder="(id) => {
|
||||
selectedOrder = filteredOrders.find(order => order.id === id);
|
||||
}"
|
||||
@selectOrder="
|
||||
(id) => {
|
||||
selectedOrder = filteredOrders.find((order) => order.id === id);
|
||||
}
|
||||
"
|
||||
@unselect="selectedOrder = null"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<SelectedOrder :order="selectedOrder" @unselect="selectedOrder = null" />
|
||||
<SelectedOrder
|
||||
:order="selectedOrder"
|
||||
@unselect="selectedOrder = null"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -15,30 +15,29 @@ const progressUnfilled = computed(() => `var(--bulma-${props.color}-85)`);
|
||||
<p :class="`has-text-${color}-40`">{{ name }}</p>
|
||||
<p :class="['fs-18 font-bold', `has-text-${color}-30`]">{{ value }}</p>
|
||||
</div>
|
||||
<progress
|
||||
<progress
|
||||
:class="['progress is-small mt-2', `is-${color}`]"
|
||||
value="20"
|
||||
max="100"
|
||||
>
|
||||
</progress>
|
||||
></progress>
|
||||
</div>
|
||||
<div
|
||||
<div
|
||||
v-if="index < 4"
|
||||
class="is-flex is-justify-content-center is-align-items-center"
|
||||
style="width: 60px; height: 48px"
|
||||
>
|
||||
<Icon
|
||||
name="material-symbols:arrow-forward-rounded"
|
||||
<Icon
|
||||
name="material-symbols:arrow-forward-rounded"
|
||||
:size="24"
|
||||
class="has-text-grey-70"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<style lang="scss" scoped>
|
||||
$progress-value-background-color: 'red';
|
||||
$progress-value-background-color: "red";
|
||||
|
||||
.progress {
|
||||
--bulma-size-small: 0.5rem;
|
||||
background-color: v-bind(progressUnfilled);
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
||||
@@ -1,42 +1,42 @@
|
||||
<script setup>
|
||||
import OrderDeliveryTab from '@/components/orders/OrderDeliveryTab.vue';
|
||||
import OrderHistoryTab from '@/components/orders/OrderHistoryTab.vue';
|
||||
import OrderPaymentTab from '@/components/orders/OrderPaymentTab.vue';
|
||||
import OrderProductTab from '@/components/orders/OrderProductTab.vue';
|
||||
import OrderReceiptTab from '@/components/orders/OrderReceiptTab.vue';
|
||||
import OrderDeliveryTab from "@/components/orders/OrderDeliveryTab.vue";
|
||||
import OrderHistoryTab from "@/components/orders/OrderHistoryTab.vue";
|
||||
import OrderPaymentTab from "@/components/orders/OrderPaymentTab.vue";
|
||||
import OrderProductTab from "@/components/orders/OrderProductTab.vue";
|
||||
import OrderReceiptTab from "@/components/orders/OrderReceiptTab.vue";
|
||||
|
||||
const props = defineProps({
|
||||
order: Object
|
||||
order: Object,
|
||||
});
|
||||
|
||||
const { $dayjs, $numtoString } = useNuxtApp();
|
||||
const emit = defineEmits(['unselect']);
|
||||
const emit = defineEmits(["unselect"]);
|
||||
|
||||
const tabs = [
|
||||
{
|
||||
name: 'Chi tiết đơn',
|
||||
heading: 'Chi tiết sản phẩm',
|
||||
icon: 'material-symbols:deployed-code-outline'
|
||||
name: "Chi tiết đơn",
|
||||
heading: "Chi tiết sản phẩm",
|
||||
icon: "material-symbols:deployed-code-outline",
|
||||
},
|
||||
{
|
||||
name: 'Giao hàng',
|
||||
heading: 'Thông tin giao hàng',
|
||||
icon: 'material-symbols:delivery-truck-speed-outline-rounded'
|
||||
name: "Giao hàng",
|
||||
heading: "Thông tin giao hàng",
|
||||
icon: "material-symbols:delivery-truck-speed-outline-rounded",
|
||||
},
|
||||
{
|
||||
name: 'Hoá đơn',
|
||||
heading: 'Hoá đơn',
|
||||
icon: 'material-symbols:receipt-long-outline-rounded'
|
||||
name: "Hoá đơn",
|
||||
heading: "Hoá đơn",
|
||||
icon: "material-symbols:receipt-long-outline-rounded",
|
||||
},
|
||||
{
|
||||
name: 'Thanh toán',
|
||||
heading: 'Thanh toán',
|
||||
icon: 'material-symbols:credit-card-outline'
|
||||
name: "Thanh toán",
|
||||
heading: "Thanh toán",
|
||||
icon: "material-symbols:credit-card-outline",
|
||||
},
|
||||
{
|
||||
name: 'Lịch sử',
|
||||
heading: 'Lịch sử đơn hàng',
|
||||
icon: 'material-symbols:history-rounded'
|
||||
name: "Lịch sử",
|
||||
heading: "Lịch sử đơn hàng",
|
||||
icon: "material-symbols:history-rounded",
|
||||
},
|
||||
];
|
||||
|
||||
@@ -44,45 +44,64 @@ const activeTab = ref(tabs[0]);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div v-if="order" class="cell relative fs-14">
|
||||
<div
|
||||
v-if="order"
|
||||
class="cell relative fs-14"
|
||||
>
|
||||
<div class="card">
|
||||
<button
|
||||
@click="emit('unselect')"
|
||||
class="button is-white rounded-full has-text-grey absolute size-8 is-flex is-justify-content-center is-align-items-center"
|
||||
style="right: 0.5rem; top: 0.5rem;"
|
||||
style="right: 0.5rem; top: 0.5rem"
|
||||
>
|
||||
<span class="icon">
|
||||
<Icon name="material-symbols:close-rounded" :size="22" />
|
||||
<Icon
|
||||
name="material-symbols:close-rounded"
|
||||
:size="22"
|
||||
/>
|
||||
</span>
|
||||
</button>
|
||||
<div class="card-content">
|
||||
<div>
|
||||
<div class="is-flex is-gap-2 is-align-items-center">
|
||||
<span class="fs-17 font-bold">{{ order.code }}</span>
|
||||
<span :class="[
|
||||
'tag rounded-full',
|
||||
`has-background-${order.status__color}-80 has-text-${order.status__color}-25`
|
||||
]">
|
||||
<span
|
||||
:class="[
|
||||
'tag rounded-full',
|
||||
`has-background-${order.status__color}-80 has-text-${order.status__color}-25`,
|
||||
]"
|
||||
>
|
||||
{{ order.status__name }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="is-flex is-gap-0.5 is-flex-direction-column mt-2">
|
||||
<div class="is-flex is-gap-1 is-align-items-center">
|
||||
<Icon name="material-symbols:person-outline-rounded" :size="18" />
|
||||
<Icon
|
||||
name="material-symbols:person-outline-rounded"
|
||||
:size="18"
|
||||
/>
|
||||
<p>{{ order.customer__name }}</p>
|
||||
</div>
|
||||
<div class="is-flex is-gap-1 is-align-items-center">
|
||||
<Icon name="material-symbols:call-outline-rounded" :size="18" />
|
||||
<Icon
|
||||
name="material-symbols:call-outline-rounded"
|
||||
:size="18"
|
||||
/>
|
||||
<p>{{ order.customer__phone }}</p>
|
||||
</div>
|
||||
<div class="is-flex is-gap-1 is-align-items-center">
|
||||
<Icon name="material-symbols:calendar-today-outline-rounded" :size="18" />
|
||||
<p>{{ $dayjs(order.create_time).format('LL') }}</p>
|
||||
<Icon
|
||||
name="material-symbols:calendar-today-outline-rounded"
|
||||
:size="18"
|
||||
/>
|
||||
<p>{{ $dayjs(order.create_time).format("LL") }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="p-4 has-background-primary-95 rounded-lg mt-6">
|
||||
<p>Tổng giá trị đơn hàng</p>
|
||||
<p class="font-bold fs-28">{{ $numtoString(order.total, { hasUnit: true }) }}</p>
|
||||
<p class="font-bold fs-28">
|
||||
{{ $numtoString(order.total, { hasUnit: true }) }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<hr class="m-0" />
|
||||
@@ -106,20 +125,38 @@ const activeTab = ref(tabs[0]);
|
||||
<hr class="m-0" />
|
||||
<div id="tab-content">
|
||||
<div class="is-flex is-gap-1 mb-4">
|
||||
<Icon :name="activeTab.icon" :size="21" />
|
||||
<Icon
|
||||
:name="activeTab.icon"
|
||||
:size="21"
|
||||
/>
|
||||
<span class="fs-15 font-semibold">{{ activeTab.heading }}</span>
|
||||
</div>
|
||||
<div>
|
||||
<OrderProductTab v-if="activeTab.name === 'Chi tiết đơn'" :order="order" />
|
||||
<OrderDeliveryTab v-else-if="activeTab.name === 'Giao hàng'" :order="order" />
|
||||
<OrderReceiptTab v-else-if="activeTab.name === 'Hoá đơn'" :order="order" />
|
||||
<OrderPaymentTab v-else-if="activeTab.name === 'Thanh toán'" :order="order" />
|
||||
<OrderHistoryTab v-else-if="activeTab.name === 'Lịch sử'" :order="order" />
|
||||
<OrderProductTab
|
||||
v-if="activeTab.name === 'Chi tiết đơn'"
|
||||
:order="order"
|
||||
/>
|
||||
<OrderDeliveryTab
|
||||
v-else-if="activeTab.name === 'Giao hàng'"
|
||||
:order="order"
|
||||
/>
|
||||
<OrderReceiptTab
|
||||
v-else-if="activeTab.name === 'Hoá đơn'"
|
||||
:order="order"
|
||||
/>
|
||||
<OrderPaymentTab
|
||||
v-else-if="activeTab.name === 'Thanh toán'"
|
||||
:order="order"
|
||||
/>
|
||||
<OrderHistoryTab
|
||||
v-else-if="activeTab.name === 'Lịch sử'"
|
||||
:order="order"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<style scoped>
|
||||
.card-content {
|
||||
@@ -135,4 +172,4 @@ const activeTab = ref(tabs[0]);
|
||||
--bulma-tabs-toggle-link-active-border-color: var(--bulma-link-90);
|
||||
--bulma-tabs-toggle-link-active-color: var(--bulma-link-40);
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user