This commit is contained in:
Viet An
2026-06-18 11:57:37 +07:00
parent 5302e685a4
commit 8b07ab4e65
34 changed files with 90 additions and 65 deletions

View File

@@ -1,5 +1,3 @@
@use "bulma/sass/utilities/initial-variables.scss" as *;
[data-theme="light"],
.theme-light {
--bulma-block-spacing: 1rem;
@@ -7,7 +5,7 @@
.card {
--bulma-card-shadow: none;
border: 1px solid $grey-lighter;
border: 1px solid var(--bulma-grey-90);
}
.title,

View File

@@ -15,6 +15,7 @@
class="modal-card max-w-8xl"
:style="{
width: $store.viewport <= 1 ? 'calc(100% - 2rem)' : width,
height,
}"
>
<header
@@ -31,11 +32,26 @@
@click="closeModal"
></button>
</header>
<section
class="modal-card-body p-4"
:style="{ minHeight: height }"
>
<Suspense>
<section class="modal-card-body p-4">
<div
v-if="error"
class="size-full is-flex"
>
<div class="w-full is-flex is-flex-direction-column is-gap-1">
<p class="has-text-danger-40">Đã lỗi khi tải dữ liệu:</p>
<pre>{{ error }}</pre>
<button
@click="closeModal"
class="button ml-auto max-w-fit"
>
Đóng
</button>
</div>
</div>
<Suspense
v-else
@resolve="loaded = true"
>
<component
:is="resolvedComponent"
v-bind="vbind"
@@ -134,6 +150,17 @@ onUnmounted(() => {
const remaining = document.getElementsByClassName("modal-background").length;
if (remaining === 0) document.documentElement.classList.remove("is-clipped");
});
const loaded = ref(false);
const error = ref();
onErrorCaptured((err) => {
// catch loading errors to display
if (!loaded) {
console.error(err);
error.value = err.message;
return false; // prevent propagating up further
}
});
</script>
<style scoped>
.modal {

View File

@@ -55,7 +55,7 @@
v-if="!v.submenu"
:class="[
'navbar-item rounded-lg is-clipped font-medium',
currentTab.code === v.code ? 'has-text-primary-50 has-background-primary-95' : 'has-text-grey-dark',
currentTab.code === v.code ? 'has-text-primary-50 has-background-primary-95' : 'has-text-grey-35',
]"
style="font-size: 13.5px"
@click="changeTab(v)"
@@ -69,7 +69,7 @@
<a
:class="[
'navbar-link rounded-lg is-arrowless font-medium',
currentTab.code === v.code ? 'has-text-primary-50 has-background-primary-95' : 'has-text-grey-dark',
currentTab.code === v.code ? 'has-text-primary-50 has-background-primary-95' : 'has-text-grey-35',
]"
@click="changeTab(v)"
style="font-size: 13.5px"

View File

@@ -11,7 +11,7 @@ const props = defineProps({
@click="$emit('justclick')"
class="rounded-full mx-0 px-0 size-10 font-bold is-flex is-justify-content-center is-align-items-center"
:style="{
border: image ? 'none' : '1px solid var(--bulma-grey-light)',
border: image ? 'none' : '1px solid var(--bulma-grey-70)',
}"
>
<figure

View File

@@ -1,7 +1,7 @@
<template>
<div
class="fs-13 font-semibold mx-0 px-0 is-flex is-justify-content-center is-align-items-center is-flex-shrink-0 rounded-full size-10"
style="border: 1px solid var(--bulma-grey-lighter)"
style="border: 1px solid var(--bulma-grey-85)"
:style="image && 'border: none'"
>
<div>
@@ -21,7 +21,7 @@ export default {
display: flex;
align-items: center;
justify-content: center;
border: var(--bulma-grey-lighter);
border: var(--bulma-grey-85);
border-radius: 50%;
}
</style>

View File

@@ -539,6 +539,6 @@
border-left-width: 1px;
}
.border-gray-300 {
border-color: var(--bulma-grey-lighter);
border-color: var(--bulma-grey-85);
}
</style>

View File

@@ -12,7 +12,7 @@ const props = defineProps({
<div
class="is-flex is-gap-2 fs-14 p-3 rounded-lg"
:style="{
border: '1px solid var(--bulma-grey-lighter)',
border: '1px solid var(--bulma-grey-85)',
}"
>
<AvatarBox :text="name.slice(0, 2)" />

View File

@@ -9,7 +9,7 @@
<Icon
name="mdi:sort-alphabetical-ascending"
:size="22"
:class="checkFilter() && 'has-text-grey-light'"
:class="checkFilter() && 'has-text-grey-70'"
/>
</span>
</button>
@@ -28,7 +28,7 @@
<Icon
name="mdi:sort-alphabetical-descending"
:size="22"
:class="checkFilter() && 'has-text-grey-light'"
:class="checkFilter() && 'has-text-grey-70'"
/>
</span>
</button>

View File

@@ -135,8 +135,9 @@
</template>
<script setup>
import { createApp } from "vue/dist/vue.esm-bundler.js";
import { ref, defineComponent } from "vue";
import { isEmpty } from "es-toolkit/compat";
import { useStore } from "~/stores/index";
const emit = defineEmits(["edit", "insert", "dataevent"]);
const {
$calc,
@@ -176,7 +177,7 @@ var currentPage = 1;
var displayFields = ref([]);
var displayData = [];
var pagedata = store[props.pagename];
let tablesetting = $copy(pagedata.tablesetting || store.tablesetting);
let tablesetting = $copy(isEmpty(pagedata.tablesetting) ? store.tablesetting : pagedata.tablesetting);
if (!Array.isArray(tablesetting)) {
tablesetting = Object.values(tablesetting);
}

View File

@@ -30,7 +30,7 @@
{{ v.name }}
</label>
</div>
<div class="has-background-white-bis mt-3 p-3 rounded-md">
<div class="has-background-white-100 mt-3 p-3 rounded-md">
<div
class="tags mb-0"
v-if="choice === 'function'"

View File

@@ -55,11 +55,11 @@
{{ v.label.indexOf(">") >= 0 ? $stripHtml(v.label, 30) : v.label }}
</a>
<a
class="tag is-delete is-marginless has-text-black-bis"
class="tag is-delete is-marginless has-text-black-5"
@click="removeFilter(i)"
></a>
</div>
<span class="help has-text-black-bis">
<span class="help has-text-black-5">
{{
v.sort
? v.sort
@@ -163,7 +163,7 @@
</template>
<span
v-else
class="has-text-grey-light"
class="has-text-grey-70"
>-</span
>
</td>

View File

@@ -237,8 +237,8 @@ input[type="color"]::-webkit-color-swatch {
.box {
box-shadow: none;
border: 1px solid var(--bulma-grey-lighter);
background-color: var(--bulma-white-bis);
border: 1px solid var(--bulma-grey-85);
background-color: var(--bulma-grey-95);
height: 100%;
}
</style>

View File

@@ -50,7 +50,7 @@
<div v-if="type === 'days'">
<div class="columns is-mobile mx-0">
<div
class="column px-2 py-1 has-text-grey-dark"
class="column px-2 py-1 has-text-grey-30"
v-for="(m, h) in dateOfWeek"
:key="h"
>

View File

@@ -68,7 +68,7 @@
</div>
</div>
<div v-if="type === 'days'">
<div class="fixed-grid has-7-cols mb-1 fs-12 font-medium has-background-white-bis has-text-grey rounded-full">
<div class="fixed-grid has-7-cols mb-1 fs-12 font-medium has-background-white-100 has-text-grey rounded-full">
<div class="grid is-gap-0">
<p
v-for="(m, h) in dateOfWeek"
@@ -93,7 +93,7 @@
>
<span
v-if="m.disabled"
class="fs-13 has-text-grey-light is-unselectable"
class="fs-13 has-text-grey-70 is-unselectable"
>
{{ m.dayPrint.replace(/^0/, "") }}
</span>

View File

@@ -10,7 +10,7 @@
class="cell"
>
<button
:class="['button is-white w-full fs-14', (i === 0 || i === 11) && 'has-text-grey-light']"
:class="['button is-white w-full fs-14', (i === 0 || i === 11) && 'has-text-grey-70']"
@click="emit('year', year)"
>
{{ year }}

View File

@@ -241,12 +241,12 @@ async function submit() {
<div
v-else
class="w-36 h-36 rounded-md is-flex is-align-items-center is-justify-content-center"
style="border: 1px solid var(--bulma-grey-lighter)"
style="border: 1px solid var(--bulma-grey-85)"
>
<Icon
name="material-symbols:add-photo-alternate-outline-rounded"
:size="40"
class="has-text-grey-light"
class="has-text-grey-70"
/>
</div>
</div>

View File

@@ -219,12 +219,12 @@ async function submit() {
<div
v-else
class="w-36 h-36 rounded-md is-flex is-align-items-center is-justify-content-center"
style="border: 1px solid var(--bulma-grey-lighter)"
style="border: 1px solid var(--bulma-grey-85)"
>
<Icon
name="material-symbols:add-photo-alternate-outline-rounded"
:size="40"
class="has-text-grey-light"
class="has-text-grey-70"
/>
</div>
</div>

View File

@@ -45,7 +45,7 @@ const emit = defineEmits("unselect");
</div>
<div>
<p class="font-semibold mb-1">{{ invItem.name }}</p>
<p class="has-text-grey-dark">SKU: {{ invItem.sku }}</p>
<p class="has-text-grey-30">SKU: {{ invItem.sku }}</p>
<p class="fs-12 has-text-grey">{{ invItem.category }}</p>
</div>
</div>
@@ -89,7 +89,7 @@ const emit = defineEmits("unselect");
</div>
<div class="mt-6">
<p class="fs-15 font-semibold mb-4">Vị trí lưu kho</p>
<div class="p-4 rounded-md has-background-white-bis">
<div class="p-4 rounded-md has-background-white-100">
<div class="is-flex is-gap-1">
<Icon
name="material-symbols:location-on-outline-rounded"
@@ -106,11 +106,11 @@ const emit = defineEmits("unselect");
</div>
<div class="mt-6">
<p class="fs-15 font-semibold mb-4">Thông tin hàng</p>
<div class="p-4 rounded-md has-background-white-bis">
<div class="p-4 rounded-md has-background-white-100">
<p class="fs-13 has-text-grey"> </p>
<p class="mt-1 is-family-monospace">{{ invItem.batch }}</p>
</div>
<div class="p-4 mt-4 rounded-md has-background-white-bis">
<div class="p-4 mt-4 rounded-md has-background-white-100">
<div class="is-flex is-gap-1 is-align-items-center">
<Icon
name="material-symbols:calendar-today-outline-rounded"
@@ -127,7 +127,7 @@ const emit = defineEmits("unselect");
<div
v-for="move in invItem.moveHistory"
:key="move.id"
class="p-4 mb-4 rounded-md has-background-white-bis has-text-grey fs-12"
class="p-4 mb-4 rounded-md has-background-white-100 has-text-grey fs-12"
>
<div class="is-flex is-justify-content-space-between mb-1">
<div class="is-flex is-gap-1 is-align-items-center">

View File

@@ -60,7 +60,7 @@
<div class="has-text-centered py-6">
<Mail
:size="64"
class="has-text-grey-light mb-4"
class="has-text-grey-70 mb-4"
/>
<p class="title is-5">No emails sent yet</p>
<p class="subtitle is-6">Sent emails will appear here</p>

View File

@@ -49,7 +49,7 @@
@click="handleRowClick(item.email, item.name, item.id)"
>
<td class="has-text-weight-medium">{{ item.name }}</td>
<td class="has-text-grey-dark">{{ item.email }}</td>
<td class="has-text-grey-30">{{ item.email }}</td>
</tr>
</template>
</tbody>

View File

@@ -44,15 +44,15 @@
class="fixed-grid has-3-cols is-family-monospace"
>
<div class="grid">
<div class="cell p-2 rounded has-background-white-ter has-text-centered">
<div class="cell p-2 rounded has-background-white-95 has-text-centered">
<p class="fs-11 is-uppercase has-text-grey">width</p>
<p class="font-semibold">{{ coordinates.width }}</p>
</div>
<div class="cell p-2 rounded has-background-white-ter has-text-centered">
<div class="cell p-2 rounded has-background-white-95 has-text-centered">
<p class="fs-11 is-uppercase has-text-grey">height</p>
<p class="font-semibold">{{ coordinates.height }}</p>
</div>
<div class="cell p-2 rounded has-background-white-ter has-text-centered">
<div class="cell p-2 rounded has-background-white-95 has-text-centered">
<p class="fs-11 is-uppercase has-text-grey">ratio</p>
<p class="font-semibold">{{ coordinates.ratio }}</p>
</div>

View File

@@ -23,12 +23,12 @@
v-else
@click="openImage()"
class="size-35 rounded-md is-clickable is-flex is-justify-content-center is-align-items-center"
style="border: 1px dashed var(--bulma-grey-light)"
style="border: 1px dashed var(--bulma-grey-70)"
>
<Icon
name="material-symbols:add-photo-alternate-outline-rounded"
:size="50"
class="has-text-grey-light"
class="has-text-grey-70"
/>
</div>
<div>

View File

@@ -11,7 +11,6 @@ function openModal() {
component: "orders/SelectedOrder",
title: "Chi tiết đơn hàng",
width: "75%",
height: "500px",
vbind: {
invoice: props.invoice,
},

View File

@@ -64,7 +64,7 @@ const historyItems = [
:class="`has-text-${item.color}-40`"
/>
<div
class="is-flex-grow-1 has-background-grey-lighter rounded-full"
class="is-flex-grow-1 has-background-grey-85 rounded-full"
style="width: 3px"
></div>
</div>

View File

@@ -36,7 +36,7 @@ function openModal() {
<div class="is-flex is-flex-direction-column is-gap-2">
<!-- customer info -->
<div>
<p class="has-text-grey-darker">{{ order.customer__name }}</p>
<p class="has-text-grey-20">{{ order.customer__name }}</p>
<div class="has-text-grey fs-13 mt-1 is-flex is-gap-1 is-align-items-center">
<Icon name="material-symbols:call-outline-rounded" />
<p>{{ order.customer__phone }}</p>
@@ -44,12 +44,12 @@ function openModal() {
</div>
<!-- product info -->
<div>
<p class="fs-24 has-text-grey-darker font-bold">
<p class="fs-24 has-text-grey-20 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 has-background-grey-lighter" />
<hr class="m-0 has-background-grey-85" />
<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

View File

@@ -8,7 +8,7 @@ const { $formatNum } = useNuxtApp();
<template>
<div>
<div class="is-flex is-gap-2">
<div class="is-flex-grow-1 p-3 rounded-md has-background-white-bis">
<div class="is-flex-grow-1 p-3 rounded-md has-background-white-100">
<p class="fs-13 has-text-grey">Tổng tiền</p>
<p class="font-bold">
{{ $formatNum(invoice.total, { hasUnit: true }) }}

View File

@@ -43,7 +43,7 @@ const phases = [
v-bind="phase"
/>
</div>
<hr class="has-background-grey-lighter" />
<hr class="has-background-grey-85" />
<div class="is-flex is-justify-content-space-between">
<p>Tổng đơn hàng</p>
<p class="fs-18 font-semibold">

View File

@@ -27,12 +27,12 @@ const invoiceProducts = computed(() => {
<div
v-for="product in invoiceProducts"
:key="product.id"
class="p-3 has-background-white-ter rounded-md"
class="p-3 has-background-white-95 rounded-md"
>
<div class="is-flex is-justify-content-space-between is-align-items-flex-end">
<div>
<p class="font-semibold">{{ product.variant__product__name }}</p>
<div class="is-flex is-gap-8 fs-13 has-text-grey-dark mt-1">
<div class="is-flex is-gap-8 fs-13 has-text-grey-30 mt-1">
<p>SL: {{ product.amount }}</p>
<p>Đơn giá: {{ $formatNum(product.price, { hasUnit: true }) }}</p>
</div>
@@ -47,15 +47,15 @@ const invoiceProducts = computed(() => {
<table class="table is-fullwidth is-bordered fs-14 mb-8">
<tbody class="has-text-right">
<tr>
<td class="has-text-grey-dark">Tổng tiền hàng</td>
<td class="has-text-grey-30">Tổng tiền hàng</td>
<td>{{ $formatNum(invoice.total_amount, { hasUnit: true }) }}</td>
</tr>
<tr>
<td class="has-text-grey-dark">Phí vận chuyển</td>
<td class="has-text-grey-30">Phí vận chuyển</td>
<td>{{ $formatNum(invoice.shipping_fee, { hasUnit: true }) }}</td>
</tr>
<tr>
<td class="has-text-grey-dark">Giảm giá</td>
<td class="has-text-grey-30">Giảm giá</td>
<td>{{ $formatNum(invoice.discount_amount, { hasUnit: true }) }}</td>
</tr>
<tr class="font-bold">

View File

@@ -9,7 +9,7 @@ const props = defineProps({
<Icon
name="material-symbols:receipt-long-outline-rounded"
:size="50"
class="has-text-grey-light"
class="has-text-grey-70"
/>
<p>Chưa hoá đơn</p>
<button class="button is-purple">Tạo hoá đơn</button>

View File

@@ -25,7 +25,7 @@ const emit = defineEmits(["selectOrder", "unselect"]);
`has-background-${status.color}-90`,
]"
>
<p class="font-semibold has-text-grey-darker">{{ status.name }}</p>
<p class="font-semibold has-text-grey-20">{{ 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)` }"
@@ -33,8 +33,8 @@ const emit = defineEmits(["selectOrder", "unselect"]);
{{ orders.filter((o) => o.status === status.id).length }}
</p>
</div>
<hr class="m-0 has-background-grey-lighter" />
<div class="has-background-white-bis p-4">
<hr class="m-0 has-background-grey-85" />
<div class="has-background-white-100 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)"

View File

@@ -29,7 +29,7 @@ const progressUnfilled = computed(() => `var(--bulma-${props.color}-85)`);
<Icon
name="material-symbols:arrow-forward-rounded"
:size="24"
class="has-text-grey-light"
class="has-text-grey-70"
/>
</div>
</template>

View File

@@ -99,7 +99,7 @@ const isValid = computed(() => {
:name="
addressRef.is_default ? 'material-symbols:check-box-rounded' : 'material-symbols:check-box-outline-blank'
"
:class="['is-clickable', addressRef.is_default ? 'has-text-primary' : 'has-text-grey-light']"
:class="['is-clickable', addressRef.is_default ? 'has-text-primary' : 'has-text-grey-70']"
:size="24"
@click="addressRef.is_default = !addressRef.is_default"
/>

View File

@@ -268,7 +268,7 @@ provide("pos", {
</div>
<p
v-else
class="has-text-grey-light py-4 has-text-centered"
class="has-text-grey-70 py-4 has-text-centered"
>
Chưa chọn khách hàng
</p>

View File

@@ -55,7 +55,7 @@ setTimeout(() => store.commit("snackbar", undefined), 2500);
margin-inline: auto;
width: fit-content;
max-width: min(500px, 90vw);
background-color: hsl(from var(--bulma-grey-darker) h s l / 0.85);
background-color: hsl(from var(--bulma-grey-20) h s l / 0.85);
}
.button.is-ghost {