changes
This commit is contained in:
@@ -129,18 +129,12 @@ $size: (
|
|||||||
// Block Layout
|
// Block Layout
|
||||||
.blockdiv {
|
.blockdiv {
|
||||||
max-width: 1900px !important;
|
max-width: 1900px !important;
|
||||||
padding: 60px 15px 40px 15px;
|
padding: 1rem 2rem 2rem;
|
||||||
|
@include mobile { padding: 1rem; }
|
||||||
@include until($desktop) { padding: 65px 20px 30px 20px; }
|
|
||||||
@include mobile { padding: 65px 16px 30px 16px; }
|
|
||||||
|
|
||||||
.columns .column {
|
.columns .column {
|
||||||
@include mobile { padding-left: 0; padding-right: 0; }
|
@include mobile { padding-left: 0; padding-right: 0; }
|
||||||
}
|
}
|
||||||
|
|
||||||
.padding-desktop {
|
|
||||||
@media screen and (min-width: $desktop) { padding-left: 20px; padding-right: 20px; }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tooltip Styles
|
// Tooltip Styles
|
||||||
|
|||||||
@@ -1,81 +1,81 @@
|
|||||||
<template>
|
<template>
|
||||||
<nav class="navbar is-fixed-top has-shadow px-3" role="navigation">
|
<nav class="navbar has-shadow sticky px-3" style="top: 0" role="navigation">
|
||||||
<div class="navbar-brand mr-5">
|
<div class="navbar-brand mr-5">
|
||||||
<span class="navbar-item is-gap-1">
|
<span class="navbar-item is-gap-1">
|
||||||
<div style="width: 16px; height: 16px" class="has-background-primary rounded-full"></div>
|
<div style="width: 16px; height: 16px" class="has-background-primary rounded-full"></div>
|
||||||
<span class="fs-17 font-semibold has-text-primary">{{$dayjs().format('DD/MM')}}</span>
|
<span class="fs-17 font-semibold has-text-primary">{{$dayjs().format('DD/MM')}}</span>
|
||||||
</span>
|
</span>
|
||||||
<a
|
<a
|
||||||
class="navbar-item p-0 has-text-primary"
|
class="navbar-item p-0 has-text-primary"
|
||||||
@click="changeTab(leftmenu[0])"
|
@click="changeTab(leftmenu[0])"
|
||||||
>
|
>
|
||||||
<svg
|
<svg
|
||||||
style="max-height: none; width: 44px"
|
style="max-height: none; width: 44px"
|
||||||
width="80" height="80" viewBox="0 0 80 80" xmlns="http://www.w3.org/2000/svg">
|
width="80" height="80" viewBox="0 0 80 80" xmlns="http://www.w3.org/2000/svg">
|
||||||
<path fill="currentColor" d="M40 8C57.6731 8 72 22.3269 72 40C72 57.6731 57.6731 72 40 72C22.3269 72 8 57.6731 8 40C8 22.3269 22.3269 8 40 8ZM15.7285 31.5762V49.2266H21.9854C23.778 49.2266 25.3185 48.8727 26.6055 48.166C27.898 47.4593 28.8887 46.4453 29.5781 45.124C30.2733 43.8025 30.6211 42.2224 30.6211 40.3838C30.6211 38.5511 30.2733 36.9768 29.5781 35.6611C28.8887 34.3455 27.9033 33.3367 26.6221 32.6357C25.3409 31.9292 23.8123 31.5762 22.0371 31.5762H15.7285ZM33.3857 49.2266H45.3135V46.1494H37.1172V41.9355H44.667V38.8584H37.1172V34.6533H45.2793V31.5762H33.3857V49.2266ZM53.3818 49.2266H58.1914L64.2754 31.5762H60.1387L55.8643 44.9863H55.7002L51.4346 31.5762H47.2891L53.3818 49.2266ZM21.8389 34.7734C22.942 34.7734 23.8704 34.9687 24.623 35.3594C25.3756 35.75 25.9411 36.3593 26.3203 37.1865C26.7052 38.0138 26.8984 39.0797 26.8984 40.3838C26.8984 41.6995 26.7053 42.7743 26.3203 43.6074C25.9411 44.4346 25.3726 45.047 24.6143 45.4434C23.8617 45.8339 22.9339 46.0292 21.8311 46.0293H19.4609V34.7734H21.8389Z" />
|
<path fill="currentColor" d="M40 8C57.6731 8 72 22.3269 72 40C72 57.6731 57.6731 72 40 72C22.3269 72 8 57.6731 8 40C8 22.3269 22.3269 8 40 8ZM15.7285 31.5762V49.2266H21.9854C23.778 49.2266 25.3185 48.8727 26.6055 48.166C27.898 47.4593 28.8887 46.4453 29.5781 45.124C30.2733 43.8025 30.6211 42.2224 30.6211 40.3838C30.6211 38.5511 30.2733 36.9768 29.5781 35.6611C28.8887 34.3455 27.9033 33.3367 26.6221 32.6357C25.3409 31.9292 23.8123 31.5762 22.0371 31.5762H15.7285ZM33.3857 49.2266H45.3135V46.1494H37.1172V41.9355H44.667V38.8584H37.1172V34.6533H45.2793V31.5762H33.3857V49.2266ZM53.3818 49.2266H58.1914L64.2754 31.5762H60.1387L55.8643 44.9863H55.7002L51.4346 31.5762H47.2891L53.3818 49.2266ZM21.8389 34.7734C22.942 34.7734 23.8704 34.9687 24.623 35.3594C25.3756 35.75 25.9411 36.3593 26.3203 37.1865C26.7052 38.0138 26.8984 39.0797 26.8984 40.3838C26.8984 41.6995 26.7053 42.7743 26.3203 43.6074C25.9411 44.4346 25.3726 45.047 24.6143 45.4434C23.8617 45.8339 22.9339 46.0292 21.8311 46.0293H19.4609V34.7734H21.8389Z" />
|
||||||
</svg>
|
</svg>
|
||||||
</a>
|
</a>
|
||||||
<a
|
<a
|
||||||
role="button"
|
role="button"
|
||||||
class="navbar-burger"
|
class="navbar-burger"
|
||||||
id="burger"
|
id="burger"
|
||||||
aria-label="menu"
|
aria-label="menu"
|
||||||
aria-expanded="false"
|
aria-expanded="false"
|
||||||
data-target="navMenu"
|
data-target="navMenu"
|
||||||
@click="handleClick()"
|
@click="handleClick()"
|
||||||
>
|
>
|
||||||
<span aria-hidden="true"></span>
|
<span aria-hidden="true"></span>
|
||||||
<span aria-hidden="true"></span>
|
<span aria-hidden="true"></span>
|
||||||
<span aria-hidden="true"></span>
|
<span aria-hidden="true"></span>
|
||||||
<span aria-hidden="true"></span>
|
<span aria-hidden="true"></span>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="navbar-menu" id="navMenu">
|
<div class="navbar-menu" id="navMenu">
|
||||||
<div class="navbar-start is-gap-1 is-align-items-center" style="min-width: 650px;">
|
<div class="navbar-start is-gap-1 is-align-items-center" >
|
||||||
<template v-for="(v, i) in leftmenu" :key="i" :id="v.code">
|
<template v-for="(v, i) in leftmenu" :key="i" :id="v.code">
|
||||||
<a class="navbar-item rounded-lg is-clipped p-0" v-if="!v.submenu" @click="changeTab(v)">
|
<a class="navbar-item rounded-lg is-clipped p-0" v-if="!v.submenu" @click="changeTab(v)">
|
||||||
|
<span :class="[
|
||||||
|
'px-3 py-2 fs-14 font-medium',
|
||||||
|
currentTab.code === v.code ? 'has-text-primary-50 has-background-primary-95' : 'has-text-grey-30'
|
||||||
|
]">
|
||||||
|
{{ v[lang] }}
|
||||||
|
</span>
|
||||||
|
</a>
|
||||||
|
<div class="navbar-item has-dropdown is-hoverable" v-else>
|
||||||
|
<a class="navbar-item px-2" @click="changeTab(v)">
|
||||||
<span :class="[
|
<span :class="[
|
||||||
'px-3 py-2 fs-14 font-medium',
|
'px-3 py-1 font-medium',
|
||||||
currentTab.code === v.code ? 'has-text-primary-50 has-background-primary-95' : 'has-text-grey-30'
|
currentTab.code === v.code ? 'has-text-primary-bold has-background-primary-soft' : 'has-text-grey-30'
|
||||||
]">
|
]">
|
||||||
{{ v[lang] }}
|
<span>{{ v[lang] }}</span>
|
||||||
|
<SvgIcon
|
||||||
|
style="padding-top: 5px"
|
||||||
|
v-bind="{ name: 'down2.svg', type: currentTab.code === v.code ? 'white' : 'dark', size: 15 }"
|
||||||
|
>
|
||||||
|
</SvgIcon>
|
||||||
</span>
|
</span>
|
||||||
</a>
|
</a>
|
||||||
<div class="navbar-item has-dropdown is-hoverable" v-else>
|
<div class="navbar-dropdown has-background-light">
|
||||||
<a class="navbar-item px-2" @click="changeTab(v)">
|
<a
|
||||||
<span :class="[
|
class="navbar-item has-background-light py-1 border-bottom"
|
||||||
'px-3 py-1 font-medium',
|
v-for="x in v.submenu"
|
||||||
currentTab.code === v.code ? 'has-text-primary-bold has-background-primary-soft' : 'has-text-grey-30'
|
@click="changeTab(v, x)"
|
||||||
]">
|
>
|
||||||
<span>{{ v[lang] }}</span>
|
{{ x[lang] }}
|
||||||
<SvgIcon
|
|
||||||
style="padding-top: 5px"
|
|
||||||
v-bind="{ name: 'down2.svg', type: currentTab.code === v.code ? 'white' : 'dark', size: 15 }"
|
|
||||||
>
|
|
||||||
</SvgIcon>
|
|
||||||
</span>
|
|
||||||
</a>
|
</a>
|
||||||
<div class="navbar-dropdown has-background-light">
|
|
||||||
<a
|
|
||||||
class="navbar-item has-background-light py-1 border-bottom"
|
|
||||||
v-for="x in v.submenu"
|
|
||||||
@click="changeTab(v, x)"
|
|
||||||
>
|
|
||||||
{{ x[lang] }}
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</div>
|
||||||
</div>
|
</template>
|
||||||
<div class="navbar-end">
|
|
||||||
<a class="navbar-item" @click="changeTab(tabConfig)" v-if="tabConfig">
|
|
||||||
<SvgIcon v-bind="{ name: 'configuration.svg', type: 'findata', size: 24 }"></SvgIcon>
|
|
||||||
</a>
|
|
||||||
<a class="navbar-item" @click="openProfile()" v-if="avatar">
|
|
||||||
<Avatarbox v-bind="avatar"></Avatarbox>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
<div v-if="false" class="navbar-end">
|
||||||
|
<a class="navbar-item" @click="changeTab(tabConfig)" v-if="tabConfig">
|
||||||
|
<SvgIcon v-bind="{ name: 'configuration.svg', type: 'findata', size: 24 }"></SvgIcon>
|
||||||
|
</a>
|
||||||
|
<a class="navbar-item" @click="openProfile()" v-if="avatar">
|
||||||
|
<Avatarbox v-bind="avatar"></Avatarbox>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
</template>
|
</template>
|
||||||
<script setup>
|
<script setup>
|
||||||
@@ -127,9 +127,9 @@ const menu = [
|
|||||||
index: 0,
|
index: 0,
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
if($store.rights.length>0) {
|
// if($store.rights.length>0) {
|
||||||
menu = menu.filter(v=>$findIndex($store.rights, {setting: v.id})>=0)
|
// menu = menu.filter(v=>$findIndex($store.rights, {setting: v.id})>=0)
|
||||||
}
|
// }
|
||||||
if(menu.length===0) {
|
if(menu.length===0) {
|
||||||
$snackbar($store.lang==='vi'? 'Bạn không có quyền truy cập' : 'You do not have permission to access.')
|
$snackbar($store.lang==='vi'? 'Bạn không có quyền truy cập' : 'You do not have permission to access.')
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -68,11 +68,12 @@ const highlights = [
|
|||||||
<div class="grid">
|
<div class="grid">
|
||||||
<DashboardHighlightCard
|
<DashboardHighlightCard
|
||||||
v-for="highlight in highlights"
|
v-for="highlight in highlights"
|
||||||
|
:key="highlight.name"
|
||||||
v-bind="highlight"
|
v-bind="highlight"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="fixed-grid has-3-cols">
|
<div class="fixed-grid has-1-cols-mobile has-3-cols">
|
||||||
<div class="grid">
|
<div class="grid">
|
||||||
<div class="cell is-col-span-2">
|
<div class="cell is-col-span-2">
|
||||||
<RevenueChart />
|
<RevenueChart />
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
|
import DeliveryInteractive from '@/components/dashboard/DeliveryInteractive.vue';
|
||||||
import Driver from '@/components/dashboard/Driver.vue';
|
import Driver from '@/components/dashboard/Driver.vue';
|
||||||
|
|
||||||
const drivers = [
|
const drivers = [
|
||||||
@@ -32,11 +33,11 @@ const drivers = [
|
|||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-content">
|
<div class="card-content">
|
||||||
<p class="fs-17 font-semibold mb-4">Giao nhận & Tài xế</p>
|
<p class="fs-17 font-semibold mb-4">Giao nhận & Tài xế</p>
|
||||||
<div class="fixed-grid has-3-cols">
|
<div class="fixed-grid has-1-cols-mobile has-3-cols">
|
||||||
<div class="grid">
|
<div class="grid">
|
||||||
<div class="cell is-col-span-2">
|
<div class="cell is-col-span-2">
|
||||||
<div style="border-radius: 0.5rem; overflow: hidden">
|
<div>
|
||||||
<NuxtImg src="/map-demo.png" class="w-full" />
|
<DeliveryInteractive />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="cell is-flex is-flex-direction-column is-gap-2">
|
<div class="cell is-flex is-flex-direction-column is-gap-2">
|
||||||
|
|||||||
477
app/components/dashboard/DeliveryInteractive.vue
Normal file
477
app/components/dashboard/DeliveryInteractive.vue
Normal file
@@ -0,0 +1,477 @@
|
|||||||
|
<template>
|
||||||
|
<div
|
||||||
|
class="relative w-full has-background-blue-95 rounded-lg is-clipped"
|
||||||
|
style="height: 360px"
|
||||||
|
>
|
||||||
|
<div class="absolute inset-0 w-full h-full opacity-20"><div class="absolute w-full border-t border-gray-300" style="top: 20%;"></div><div class="absolute w-full border-t border-gray-300" style="top: 40%;"></div><div class="absolute w-full border-t border-gray-300" style="top: 60%;"></div><div class="absolute w-full border-t border-gray-300" style="top: 80%;"></div><div class="absolute w-full border-t border-gray-300" style="top: 100%;"></div><div class="absolute h-full border-l border-gray-300" style="left: 20%;"></div><div class="absolute h-full border-l border-gray-300" style="left: 40%;"></div><div class="absolute h-full border-l border-gray-300" style="left: 60%;"></div><div class="absolute h-full border-l border-gray-300" style="left: 80%;"></div><div class="absolute h-full border-l border-gray-300" style="left: 100%;"></div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div
|
||||||
|
class="absolute transform -translate-x-1/2 -translate-y-full"
|
||||||
|
style="left: 33.3333%; top: 40%"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="currentColor"
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-width="2"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
class="lucide lucide-map-pin w-6 h-6 has-text-orange-50"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M20 10c0 4.993-5.539 10.193-7.399 11.799a1 1 0 0 1-1.202 0C9.539 20.193 4 14.993 4 10a8 8 0 0 1 16 0"
|
||||||
|
></path>
|
||||||
|
<circle cx="12" cy="10" r="3"></circle>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="absolute transform -translate-x-1/2 -translate-y-full"
|
||||||
|
style="left: 56.6667%; top: 60%"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="currentColor"
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-width="2"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
class="lucide lucide-map-pin w-6 h-6 has-text-green-50"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M20 10c0 4.993-5.539 10.193-7.399 11.799a1 1 0 0 1-1.202 0C9.539 20.193 4 14.993 4 10a8 8 0 0 1 16 0"
|
||||||
|
></path>
|
||||||
|
<circle cx="12" cy="10" r="3"></circle>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="absolute transform -translate-x-1/2 -translate-y-full"
|
||||||
|
style="left: 10%; top: 28%"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="currentColor"
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-width="2"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
class="lucide lucide-map-pin w-6 h-6 has-text-orange-50"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M20 10c0 4.993-5.539 10.193-7.399 11.799a1 1 0 0 1-1.202 0C9.539 20.193 4 14.993 4 10a8 8 0 0 1 16 0"
|
||||||
|
></path>
|
||||||
|
<circle cx="12" cy="10" r="3"></circle>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="absolute transform -translate-x-1/2 -translate-y-full"
|
||||||
|
style="left: 83.3333%; top: 80%"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="currentColor"
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-width="2"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
class="lucide lucide-map-pin w-6 h-6 has-text-green-50"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M20 10c0 4.993-5.539 10.193-7.399 11.799a1 1 0 0 1-1.202 0C9.539 20.193 4 14.993 4 10a8 8 0 0 1 16 0"
|
||||||
|
></path>
|
||||||
|
<circle cx="12" cy="10" r="3"></circle>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="absolute transform -translate-x-1/2 -translate-y-full"
|
||||||
|
style="left: 40%; top: 52%"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="currentColor"
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-width="2"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
class="lucide lucide-map-pin w-6 h-6 has-text-blue-50"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M20 10c0 4.993-5.539 10.193-7.399 11.799a1 1 0 0 1-1.202 0C9.539 20.193 4 14.993 4 10a8 8 0 0 1 16 0"
|
||||||
|
></path>
|
||||||
|
<circle cx="12" cy="10" r="3"></circle>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="absolute transform -translate-x-1/2 -translate-y-1/2 transition-all duration-3000 ease-linear animate-move-random-1"
|
||||||
|
style="left: 39.3933%; top: 56.171%"
|
||||||
|
>
|
||||||
|
<div class="relative">
|
||||||
|
<div
|
||||||
|
class="w-10 h-10 rounded-full has-background-blue-50 border-2 border-white is-flex is-justify-content-center is-align-items-center"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="white"
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-width="2"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
class="lucide lucide-navigation w-5 h-5 text-white"
|
||||||
|
>
|
||||||
|
<polygon points="3 11 22 2 13 21 11 13 3 11"></polygon>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="absolute -inset-1 rounded-full has-background-blue-60 animate-ping opacity-40"
|
||||||
|
></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="absolute transform -translate-x-1/2 -translate-y-1/2 transition-all duration-3000 ease-linear animate-move-random-2"
|
||||||
|
style="left: 22.8854%; top: 33.4304%"
|
||||||
|
>
|
||||||
|
<div class="relative">
|
||||||
|
<div
|
||||||
|
class="w-10 h-10 rounded-full has-background-blue-50 border-2 border-white is-flex is-justify-content-center is-align-items-center"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="white"
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-width="2"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
class="lucide lucide-navigation w-5 h-5 text-white"
|
||||||
|
>
|
||||||
|
<polygon points="3 11 22 2 13 21 11 13 3 11"></polygon>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="absolute -inset-1 rounded-full has-background-blue-60 animate-ping opacity-40"
|
||||||
|
></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="absolute transform -translate-x-1/2 -translate-y-1/2 transition-all duration-3000 ease-linear"
|
||||||
|
style="left: 73.3333%; top: 72%"
|
||||||
|
>
|
||||||
|
<div class="relative">
|
||||||
|
<div
|
||||||
|
class="w-10 h-10 rounded-full bg-gray-400 border-2 border-white is-flex is-justify-content-center is-align-items-center"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="white"
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-width="2"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
class="lucide lucide-navigation w-5 h-5 text-white"
|
||||||
|
>
|
||||||
|
<polygon points="3 11 22 2 13 21 11 13 3 11"></polygon>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="absolute transform -translate-x-1/2 -translate-y-1/2 transition-all duration-3000 ease-linear animate-move-random-3"
|
||||||
|
style="left: 37.052%; top: 75.6278%"
|
||||||
|
>
|
||||||
|
<div class="relative">
|
||||||
|
<div
|
||||||
|
class="w-10 h-10 rounded-full has-background-blue-50 border-2 border-white is-flex is-justify-content-center is-align-items-center"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="white"
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-width="2"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
class="lucide lucide-navigation w-5 h-5 text-white"
|
||||||
|
>
|
||||||
|
<polygon points="3 11 22 2 13 21 11 13 3 11"></polygon>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="absolute -inset-1 rounded-full has-background-blue-60 animate-ping opacity-40"
|
||||||
|
></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="absolute bottom-3 right-3 backdrop-blur px-3 py-1.5 rounded-lg text-xs font-medium has-text-gray-60"
|
||||||
|
style="background-color: hsla(0, 100%, 100%, 0.9)"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-width="2"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
class="lucide lucide-map-pin w-4 h-4 inline mr-1"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M20 10c0 4.993-5.539 10.193-7.399 11.799a1 1 0 0 1-1.202 0C9.539 20.193 4 14.993 4 10a8 8 0 0 1 16 0"
|
||||||
|
></path>
|
||||||
|
<circle cx="12" cy="10" r="3"></circle></svg>Hà Nội
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<style scoped>
|
||||||
|
.absolute {
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
.relative {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
.-inset-1 {
|
||||||
|
inset: calc(var(--spacing) * -1);
|
||||||
|
}
|
||||||
|
.right-3 {
|
||||||
|
right: calc(var(--spacing) * 3);
|
||||||
|
}
|
||||||
|
.bottom-3 {
|
||||||
|
bottom: calc(var(--spacing) * 3);
|
||||||
|
}
|
||||||
|
.mr-1 {
|
||||||
|
margin-right: calc(var(--spacing) * 1);
|
||||||
|
}
|
||||||
|
.inline {
|
||||||
|
display: inline;
|
||||||
|
}
|
||||||
|
.h-3 {
|
||||||
|
height: calc(var(--spacing) * 3);
|
||||||
|
}
|
||||||
|
.h-5 {
|
||||||
|
height: calc(var(--spacing) * 5);
|
||||||
|
}
|
||||||
|
.h-6 {
|
||||||
|
height: calc(var(--spacing) * 6);
|
||||||
|
}
|
||||||
|
.h-10 {
|
||||||
|
height: calc(var(--spacing) * 10);
|
||||||
|
}
|
||||||
|
.w-3 {
|
||||||
|
width: calc(var(--spacing) * 3);
|
||||||
|
}
|
||||||
|
.w-5 {
|
||||||
|
width: calc(var(--spacing) * 5);
|
||||||
|
}
|
||||||
|
.w-6 {
|
||||||
|
width: calc(var(--spacing) * 6);
|
||||||
|
}
|
||||||
|
.w-10 {
|
||||||
|
width: calc(var(--spacing) * 10);
|
||||||
|
}
|
||||||
|
.w-full {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.-translate-x-1\/2 {
|
||||||
|
--tw-translate-x: calc(calc(1 / 2 * 100%) * -1);
|
||||||
|
translate: var(--tw-translate-x) var(--tw-translate-y);
|
||||||
|
}
|
||||||
|
.-translate-y-1\/2 {
|
||||||
|
--tw-translate-y: calc(calc(1 / 2 * 100%) * -1);
|
||||||
|
translate: var(--tw-translate-x) var(--tw-translate-y);
|
||||||
|
}
|
||||||
|
.-translate-y-full {
|
||||||
|
--tw-translate-y: -100%;
|
||||||
|
translate: var(--tw-translate-x) var(--tw-translate-y);
|
||||||
|
}
|
||||||
|
.transform {
|
||||||
|
transform: var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,);
|
||||||
|
}
|
||||||
|
.animate-ping {
|
||||||
|
animation: ping 1s cubic-bezier(0,0,0.2,1) infinite;
|
||||||
|
}
|
||||||
|
@keyframes ping {
|
||||||
|
0% {
|
||||||
|
opacity: 0.4;
|
||||||
|
transform: scale(0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
opacity: 0;
|
||||||
|
transform: scale(1.5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.animate-move-random-1 {
|
||||||
|
animation: move-random-1 30s ease-in-out infinite;
|
||||||
|
}
|
||||||
|
.animate-move-random-2 {
|
||||||
|
animation: move-random-2 60s ease-in-out infinite;
|
||||||
|
}
|
||||||
|
.animate-move-random-3 {
|
||||||
|
animation: move-random-3 50s ease-in-out infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes move-random-1 {
|
||||||
|
0% {
|
||||||
|
transform: translateX(0) translateY(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
33% {
|
||||||
|
transform: translateX(30px) translateY(24px)
|
||||||
|
}
|
||||||
|
|
||||||
|
66% {
|
||||||
|
transform: translateX(60px) translateY(12px)
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
transform: translateX(0) translateY(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes move-random-2 {
|
||||||
|
0% {
|
||||||
|
transform: translateX(0) translateY(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
23% {
|
||||||
|
transform: translateX(-20px) translateY(-36px)
|
||||||
|
}
|
||||||
|
|
||||||
|
46% {
|
||||||
|
transform: translateX(0) translateY(22px)
|
||||||
|
}
|
||||||
|
|
||||||
|
75% {
|
||||||
|
transform: translateX(30px) translateY(-12px)
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
transform: translateX(0) translateY(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes move-random-3 {
|
||||||
|
0% {
|
||||||
|
transform: translateX(0) translateY(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
10% {
|
||||||
|
transform: translateX(-30px) translateY(-15px)
|
||||||
|
}
|
||||||
|
|
||||||
|
30% {
|
||||||
|
transform: translateX(-10px) translateY(26px)
|
||||||
|
}
|
||||||
|
|
||||||
|
50% {
|
||||||
|
transform: translateX(48px) translateY(-28px)
|
||||||
|
}
|
||||||
|
|
||||||
|
80% {
|
||||||
|
transform: translateX(17px) translateY(10px)
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
transform: translateX(0) translateY(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.border-2 {
|
||||||
|
border-style: var(--tw-border-style);
|
||||||
|
border-width: 2px;
|
||||||
|
}
|
||||||
|
.border-white {
|
||||||
|
border-color: var(--color-white);
|
||||||
|
}
|
||||||
|
.bg-gray-400 {
|
||||||
|
background-color: var(--color-gray-400);
|
||||||
|
}
|
||||||
|
.bg-white\/90 {
|
||||||
|
background-color: color-mix(in srgb, #fff 90%, transparent);
|
||||||
|
@supports (color: color-mix(in lab, red, red)) {
|
||||||
|
background-color: color-mix(in oklab, var(--color-white) 90%, transparent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.px-3 {
|
||||||
|
padding-inline: calc(var(--spacing) * 3);
|
||||||
|
}
|
||||||
|
.py-1\.5 {
|
||||||
|
padding-block: calc(var(--spacing) * 1.5);
|
||||||
|
}
|
||||||
|
.text-xs {
|
||||||
|
font-size: var(--text-xs);
|
||||||
|
line-height: var(--tw-leading, var(--text-xs--line-height));
|
||||||
|
}
|
||||||
|
.font-medium {
|
||||||
|
--tw-font-weight: var(--font-weight-medium);
|
||||||
|
font-weight: var(--font-weight-medium);
|
||||||
|
}
|
||||||
|
.text-gray-600 {
|
||||||
|
color: var(--color-gray-600);
|
||||||
|
}
|
||||||
|
.text-white {
|
||||||
|
color: var(--color-white);
|
||||||
|
}
|
||||||
|
.opacity-40 {
|
||||||
|
opacity: 40%;
|
||||||
|
}
|
||||||
|
.shadow {
|
||||||
|
--tw-shadow: 0 1px 3px 0 var(--tw-shadow-color, rgb(0 0 0 / 0.1)), 0 1px 2px -1px var(--tw-shadow-color, rgb(0 0 0 / 0.1));
|
||||||
|
box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
|
||||||
|
}
|
||||||
|
.backdrop-blur {
|
||||||
|
--tw-backdrop-blur: blur(8px);
|
||||||
|
-webkit-backdrop-filter: var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);
|
||||||
|
backdrop-filter: var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);
|
||||||
|
}
|
||||||
|
.transition-all {
|
||||||
|
transition-property: all;
|
||||||
|
transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));
|
||||||
|
transition-duration: var(--tw-duration, var(--default-transition-duration));
|
||||||
|
}
|
||||||
|
.duration-3000 {
|
||||||
|
--tw-duration: 3000ms;
|
||||||
|
transition-duration: 3000ms;
|
||||||
|
}
|
||||||
|
.ease-linear {
|
||||||
|
--tw-ease: linear;
|
||||||
|
transition-timing-function: linear;
|
||||||
|
}
|
||||||
|
.border-t {
|
||||||
|
border-top-style: solid;
|
||||||
|
border-top-width: 1px;
|
||||||
|
}
|
||||||
|
.border-l {
|
||||||
|
border-left-style: solid;
|
||||||
|
border-left-width: 1px;
|
||||||
|
}
|
||||||
|
.border-gray-300 {
|
||||||
|
border-color: var(--bulma-grey-85);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -117,7 +117,6 @@
|
|||||||
weeks.value.map(v=>{
|
weeks.value.map(v=>{
|
||||||
v.dates = dates.filter(x=>x.week===v.week)
|
v.dates = dates.filter(x=>x.week===v.week)
|
||||||
})
|
})
|
||||||
console.log('weeks.value', weeks.value)
|
|
||||||
}
|
}
|
||||||
function nextMonth() {
|
function nextMonth() {
|
||||||
month = month + 1
|
month = month + 1
|
||||||
|
|||||||
@@ -33,6 +33,32 @@ const inventoryHighlights = [
|
|||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
|
<div class="content buttons is-justify-content-flex-end">
|
||||||
|
<button class="button fs-14">
|
||||||
|
<span class="icon">
|
||||||
|
<Icon :size="18" name="material-symbols:download-rounded" />
|
||||||
|
</span>
|
||||||
|
<span>Export</span>
|
||||||
|
</button>
|
||||||
|
<button class="button fs-14">
|
||||||
|
<span class="icon">
|
||||||
|
<Icon :size="18" name="material-symbols:upload-rounded" />
|
||||||
|
</span>
|
||||||
|
<span>Import</span>
|
||||||
|
</button>
|
||||||
|
<button class="button fs-14">
|
||||||
|
<span class="icon">
|
||||||
|
<Icon :size="18" name="material-symbols:sync" />
|
||||||
|
</span>
|
||||||
|
<span>Chuyển kho</span>
|
||||||
|
</button>
|
||||||
|
<button class="button fs-14 is-primary">
|
||||||
|
<span class="icon">
|
||||||
|
<Icon :size="18" name="material-symbols:add-2-rounded" />
|
||||||
|
</span>
|
||||||
|
<span>Điều chỉnh</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
<div class="fixed-grid has-2-cols-mobile has-4-cols">
|
<div class="fixed-grid has-2-cols-mobile has-4-cols">
|
||||||
<div class="grid">
|
<div class="grid">
|
||||||
<InventoryHighlightCard
|
<InventoryHighlightCard
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ const emit = defineEmits('unselect');
|
|||||||
<button
|
<button
|
||||||
@click="emit('unselect')"
|
@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"
|
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="z-index: 1; right: 0.5rem; top: 0.5rem;"
|
||||||
>
|
>
|
||||||
<span class="icon">
|
<span class="icon">
|
||||||
<Icon name="material-symbols:close-rounded" :size="22" />
|
<Icon name="material-symbols:close-rounded" :size="22" />
|
||||||
|
|||||||
19
app/components/orders/OrderDeliveryTab.vue
Normal file
19
app/components/orders/OrderDeliveryTab.vue
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
<script setup>
|
||||||
|
const props = defineProps({
|
||||||
|
order: Object
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<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>
|
||||||
|
</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>
|
||||||
|
</template>
|
||||||
83
app/components/orders/OrderHistoryTab.vue
Normal file
83
app/components/orders/OrderHistoryTab.vue
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
<script setup>
|
||||||
|
const props = defineProps({
|
||||||
|
order: Object
|
||||||
|
});
|
||||||
|
|
||||||
|
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'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
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'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
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'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
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'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
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'
|
||||||
|
},
|
||||||
|
]
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<div class="is-flex is-flex-direction-column is-gap-2">
|
||||||
|
<div
|
||||||
|
v-for="item in historyItems"
|
||||||
|
:key="item.id"
|
||||||
|
class="is-flex is-gap-2"
|
||||||
|
>
|
||||||
|
<div class="is-flex is-flex-direction-column is-align-items-center is-gap-0.5">
|
||||||
|
<Icon
|
||||||
|
:name="item.icon"
|
||||||
|
:size="22"
|
||||||
|
:class="`has-text-${item.color}-40`"
|
||||||
|
/>
|
||||||
|
<div class="is-flex-grow-1 has-background-grey-lighter rounded-full"
|
||||||
|
style="width: 3px"
|
||||||
|
></div>
|
||||||
|
</div>
|
||||||
|
<div class="is-flex-grow-1">
|
||||||
|
<div class="is-flex is-gap-1 is-justify-content-space-between">
|
||||||
|
<div>
|
||||||
|
<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>
|
||||||
|
</div>
|
||||||
|
<hr class="mt-4 mb-0 has-background-grey-95" style="height: 2px" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
66
app/components/orders/OrderKanbanCard.vue
Normal file
66
app/components/orders/OrderKanbanCard.vue
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
<script setup>
|
||||||
|
const props = defineProps({
|
||||||
|
order: Object
|
||||||
|
});
|
||||||
|
|
||||||
|
const { $dayjs, $shortenCurrency } = useNuxtApp();
|
||||||
|
const emit = defineEmits(['selectOrder', 'unselect']);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<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`]"
|
||||||
|
>
|
||||||
|
{{ order.payment_status__name }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="is-flex is-flex-direction-column is-gap-2">
|
||||||
|
<!-- customer info -->
|
||||||
|
<div>
|
||||||
|
<p class="has-text-grey-10">{{ 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>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- product info -->
|
||||||
|
<div>
|
||||||
|
<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>
|
||||||
|
<span>•</span>
|
||||||
|
<span>{{ $dayjs(order.create_time).format('HH:mm') }}</span>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
NV: <span>{{ order.employee__name }}</span>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<button
|
||||||
|
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' ? 'Xác nhận' : order.status__name === 'Đã xác nhận' ? 'Giao hàng' : 'Hoàn thành' }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
25
app/components/orders/OrderPaymentTab.vue
Normal file
25
app/components/orders/OrderPaymentTab.vue
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
<script setup>
|
||||||
|
const props = defineProps({
|
||||||
|
order: Object
|
||||||
|
});
|
||||||
|
const { $numtoString } = useNuxtApp();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<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>
|
||||||
|
</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>
|
||||||
|
<p class="font-bold has-text-success-30">0 đ</p>
|
||||||
|
</div>
|
||||||
|
</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>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
34
app/components/orders/OrderProductTab.vue
Normal file
34
app/components/orders/OrderProductTab.vue
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
<script setup>
|
||||||
|
const props = defineProps({
|
||||||
|
order: Object
|
||||||
|
});
|
||||||
|
|
||||||
|
const { $numtoString } = useNuxtApp();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<div class="is-flex is-flex-direction-column is-gap-2">
|
||||||
|
<div
|
||||||
|
v-for="product in order.order__products"
|
||||||
|
:key="product.id"
|
||||||
|
class="p-3 has-background-grey-95 rounded-md"
|
||||||
|
>
|
||||||
|
<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>
|
||||||
|
</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>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<hr />
|
||||||
|
<div class="font-bold is-flex is-gap-2 is-justify-content-space-between is-align-items-center">
|
||||||
|
<p class="fs-15">Tổng cộng</p>
|
||||||
|
<p class="fs-18">{{ $numtoString(order.total, { hasUnit: true }) }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
17
app/components/orders/OrderReceiptTab.vue
Normal file
17
app/components/orders/OrderReceiptTab.vue
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
<script setup>
|
||||||
|
const props = defineProps({
|
||||||
|
order: Object
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="is-flex is-flex-direction-column is-gap-2 is-align-items-center">
|
||||||
|
<Icon
|
||||||
|
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-primary has-background-purple">Tạo hoá đơn</button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
@@ -10,7 +10,7 @@ const emit = defineEmits(['selectOrder', 'unselect'])
|
|||||||
<template>
|
<template>
|
||||||
<tr
|
<tr
|
||||||
:class="['is-clickable', selected && 'is-selected']"
|
:class="['is-clickable', selected && 'is-selected']"
|
||||||
@click="selected ? emit('unselect') : emit('selectOrder', order.id) "
|
@click="selected ? emit('unselect') : emit('selectOrder', order.id)"
|
||||||
>
|
>
|
||||||
<td>
|
<td>
|
||||||
<div>
|
<div>
|
||||||
@@ -59,7 +59,15 @@ const emit = defineEmits(['selectOrder', 'unselect'])
|
|||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<button class="button is-dark fs-13 rounded-full">Xác nhận</button>
|
<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>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -35,10 +35,40 @@ const highlights = [
|
|||||||
color: 'purple',
|
color: 'purple',
|
||||||
unit: 'VNĐ'
|
unit: 'VNĐ'
|
||||||
},
|
},
|
||||||
]
|
];
|
||||||
|
|
||||||
|
const viewModes = [
|
||||||
|
{ name: 'list', icon: 'material-symbols:format-list-bulleted-rounded' },
|
||||||
|
{ name: 'grid', icon: 'material-symbols:grid-view-outline-rounded' }
|
||||||
|
];
|
||||||
|
const viewMode = ref('list');
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
|
<div class="content 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">
|
||||||
|
<li
|
||||||
|
v-for="mode in viewModes"
|
||||||
|
:key="mode.name"
|
||||||
|
:class="[mode.name === viewMode && 'is-active']"
|
||||||
|
@click="viewMode = mode.name"
|
||||||
|
>
|
||||||
|
<a class="px-3 py-1">
|
||||||
|
<span class="icon m-0">
|
||||||
|
<Icon :name="mode.icon" :size="18" />
|
||||||
|
</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<button class="button fs-14 is-primary">
|
||||||
|
<span class="icon">
|
||||||
|
<Icon :size="18" name="material-symbols:add-2-rounded" />
|
||||||
|
</span>
|
||||||
|
<span>Tạo đơn hàng</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
<div class="fixed-grid has-2-cols-mobile has-5-cols">
|
<div class="fixed-grid has-2-cols-mobile has-5-cols">
|
||||||
<div class="grid">
|
<div class="grid">
|
||||||
<OrderHighlightCard
|
<OrderHighlightCard
|
||||||
@@ -49,6 +79,13 @@ const highlights = [
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<OrderPipeline />
|
<OrderPipeline />
|
||||||
<OrdersTable />
|
<OrdersTable :viewMode="viewMode" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
<style scoped>
|
||||||
|
.tabs {
|
||||||
|
--bulma-tabs-toggle-link-active-background-color: var(--bulma-link-90);
|
||||||
|
--bulma-tabs-toggle-link-active-border-color: var(--bulma-link-90);
|
||||||
|
--bulma-tabs-toggle-link-active-color: var(--bulma-link-40);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
48
app/components/orders/OrdersKanban.vue
Normal file
48
app/components/orders/OrdersKanban.vue
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
<script setup>
|
||||||
|
import OrderKanbanCard from '@/components/orders/OrderKanbanCard.vue';
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
orders: Array,
|
||||||
|
statuses: Array,
|
||||||
|
});
|
||||||
|
|
||||||
|
const emit = defineEmits(['selectOrder', 'unselect']);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="p-5 fixed-grid has-4-cols">
|
||||||
|
<div class="grid">
|
||||||
|
<div
|
||||||
|
v-for="status in statuses"
|
||||||
|
:key="status.id"
|
||||||
|
class="card"
|
||||||
|
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`]">
|
||||||
|
<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)`}"
|
||||||
|
>
|
||||||
|
{{ 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)"
|
||||||
|
: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">
|
||||||
|
Không có đơn hàng
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
@@ -3,6 +3,10 @@ import OrderRow from '@/components/orders/OrderRow.vue';
|
|||||||
import SelectedOrder from '@/components/orders/SelectedOrder.vue';
|
import SelectedOrder from '@/components/orders/SelectedOrder.vue';
|
||||||
import { pull } from 'es-toolkit';
|
import { pull } from 'es-toolkit';
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
viewMode: String
|
||||||
|
});
|
||||||
|
|
||||||
const { $dayjs } = useNuxtApp();
|
const { $dayjs } = useNuxtApp();
|
||||||
|
|
||||||
const orders = [
|
const orders = [
|
||||||
@@ -480,7 +484,7 @@ function toggleStatus(id) {
|
|||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<div class="card">
|
<div class="card is-clipped">
|
||||||
<div class="card-content">
|
<div class="card-content">
|
||||||
<div class="is-flex is-gap-2 is-align-items-center">
|
<div class="is-flex is-gap-2 is-align-items-center">
|
||||||
<div class="field is-flex-grow-1 m-0">
|
<div class="field is-flex-grow-1 m-0">
|
||||||
@@ -556,37 +560,48 @@ function toggleStatus(id) {
|
|||||||
<div class="fixed-grid has-3-cols">
|
<div class="fixed-grid has-3-cols">
|
||||||
<div class="grid">
|
<div class="grid">
|
||||||
<div :class="['cell', selectedOrder ? 'is-col-span-2' : 'is-col-span-3']">
|
<div :class="['cell', selectedOrder ? 'is-col-span-2' : 'is-col-span-3']">
|
||||||
<div class="card">
|
<div class="card is-clipped">
|
||||||
<div class="card-content p-0">
|
<div class="card-content p-0">
|
||||||
<p class="p-5 fs-17 font-semibold is-flex is-align-items-center is-gap-1">
|
<template v-if="viewMode === 'list'">
|
||||||
<Icon name="material-symbols:list-alt-outline-rounded" :size="22" />
|
<p class="p-5 fs-17 font-semibold is-flex is-align-items-center is-gap-1">
|
||||||
<span>Danh sách đơn hàng ({{ filteredOrders.length }})</span>
|
<Icon name="material-symbols:list-alt-outline-rounded" :size="22" />
|
||||||
</p>
|
<span>Danh sách đơn hàng ({{ filteredOrders.length }})</span>
|
||||||
<table class="table is-fullwidth is-hoverable fs-13">
|
</p>
|
||||||
<thead>
|
<table class="table is-fullwidth is-hoverable fs-13">
|
||||||
<tr>
|
<thead>
|
||||||
<th class="font-semibold">Đơn hàng</th>
|
<tr>
|
||||||
<th class="font-semibold">Khách hàng</th>
|
<th class="font-semibold">Đơn hàng</th>
|
||||||
<th class="font-semibold has-text-right">Tổng tiền</th>
|
<th class="font-semibold">Khách hàng</th>
|
||||||
<th class="font-semibold has-text-centered">Trạng thái</th>
|
<th class="font-semibold has-text-right">Tổng tiền</th>
|
||||||
<th class="font-semibold">Thanh toán</th>
|
<th class="font-semibold has-text-centered">Trạng thái</th>
|
||||||
<th class="font-semibold">Giao hàng</th>
|
<th class="font-semibold">Thanh toán</th>
|
||||||
<th class="font-semibold">Ngày tạo</th>
|
<th class="font-semibold">Giao hàng</th>
|
||||||
<th class="font-semibold">Thao tác</th>
|
<th class="font-semibold">Ngày tạo</th>
|
||||||
</tr>
|
<th class="font-semibold">Thao tác</th>
|
||||||
</thead>
|
</tr>
|
||||||
<tbody>
|
</thead>
|
||||||
<OrderRow
|
<tbody>
|
||||||
v-for="order in filteredOrders"
|
<OrderRow
|
||||||
:key="order.id"
|
v-for="order in filteredOrders"
|
||||||
v-bind="{ order, selected: order.id === selectedOrder?.id }"
|
:key="order.id"
|
||||||
@selectOrder="(id) => {
|
v-bind="{ order, selected: order.id === selectedOrder?.id }"
|
||||||
selectedOrder = filteredOrders.find(order => order.id === id);
|
@selectOrder="(id) => {
|
||||||
}"
|
selectedOrder = filteredOrders.find(order => order.id === id);
|
||||||
@unselect="selectedOrder = null"
|
}"
|
||||||
/>
|
@unselect="selectedOrder = null"
|
||||||
</tbody>
|
/>
|
||||||
</table>
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</template>
|
||||||
|
<OrdersKanban
|
||||||
|
v-else
|
||||||
|
:orders="filteredOrders"
|
||||||
|
:statuses="statuses"
|
||||||
|
@selectOrder="(id) => {
|
||||||
|
selectedOrder = filteredOrders.find(order => order.id === id);
|
||||||
|
}"
|
||||||
|
@unselect="selectedOrder = null"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,10 +1,46 @@
|
|||||||
<script setup>
|
<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';
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
order: Object
|
order: Object
|
||||||
});
|
});
|
||||||
|
|
||||||
const { $dayjs, $numtoString } = useNuxtApp();
|
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: '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: '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'
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const activeTab = ref(tabs[0]);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -55,35 +91,32 @@ const emit = defineEmits(['unselect']);
|
|||||||
<button class="button fs-14 is-flex-grow-1">Ghi thanh toán</button>
|
<button class="button fs-14 is-flex-grow-1">Ghi thanh toán</button>
|
||||||
</div>
|
</div>
|
||||||
<hr class="m-0" />
|
<hr class="m-0" />
|
||||||
<div class="tabs is-toggle fs-13">
|
<div class="tabs is-toggle m-0 fs-13">
|
||||||
<ul>
|
<ul>
|
||||||
<li class="is-active">
|
<li
|
||||||
<a>
|
v-for="tab in tabs"
|
||||||
<span>Chi tiết đơn</span>
|
:key="tab.name"
|
||||||
</a>
|
:class="activeTab.name === tab.name && 'is-active'"
|
||||||
</li>
|
@click="activeTab = tab"
|
||||||
<li>
|
>
|
||||||
<a>
|
<a>{{ tab.name }}</a>
|
||||||
<span>Giao hàng</span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a>
|
|
||||||
<span>Hoá đơn</span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a>
|
|
||||||
<span>Thanh toán</span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a>
|
|
||||||
<span>Lịch sử</span>
|
|
||||||
</a>
|
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
<hr class="m-0" />
|
||||||
|
<div id="tab-content">
|
||||||
|
<div class="is-flex is-gap-1 mb-4">
|
||||||
|
<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" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,19 +1,22 @@
|
|||||||
<template>
|
<template>
|
||||||
<ClientOnly>
|
<ClientOnly>
|
||||||
<TopMenu @changetab="changeTab" />
|
<TopMenu @changetab="changeTab" />
|
||||||
</ClientOnly>
|
|
||||||
<ClientOnly>
|
|
||||||
<div class="container blockdiv has-text-text-20">
|
<div class="container blockdiv has-text-text-20">
|
||||||
<div class="fs-17 font-semibold mb-2 is-flex is-align-items-center is-gap-1" v-if="tab">
|
<div class="fs-17 font-semibold mb-2 is-flex is-align-items-center is-gap-1" v-if="tab">
|
||||||
<template v-if="subtab">
|
<template v-if="subtab">
|
||||||
<span>{{ tab[$store.lang] }}</span>
|
<span>{{ tab[$store.lang] }}</span>
|
||||||
<SvgIcon class="mx-2" v-bind="{ name: 'right.svg', size: 17, type: 'has-text-black' }"></SvgIcon>
|
<SvgIcon class="mx-2" v-bind="{ name: 'right.svg', size: 17, type: 'has-text-black' }"></SvgIcon>
|
||||||
<span>{{ subtab[$store.lang] }}</span>
|
<span>{{ subtab[$store.lang] }}</span>
|
||||||
</template>
|
</template>
|
||||||
<span v-else>{{ tab[$store.lang] }}</span>
|
<div v-else>
|
||||||
<button class="button is-primary is-light rounded-full p-1" @click="refresh()">
|
<div class="is-flex is-gap-1 is-align-items-center mb-1">
|
||||||
<Icon name="material-symbols:refresh-rounded" :size="24" />
|
<p>{{ tab[$store.lang] }}</p>
|
||||||
</button>
|
<button class="button is-primary is-light rounded-full p-1" @click="refresh()">
|
||||||
|
<Icon name="material-symbols:refresh-rounded" :size="20" />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<p class="has-text-grey fs-13 font-normal">Cập nhật: 16:25:54</p>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<KeepAlive>
|
<KeepAlive>
|
||||||
<component :is="componentMap[vbind.component]" v-bind="vbind" :key="componentKey" v-if="componentKey" />
|
<component :is="componentMap[vbind.component]" v-bind="vbind" :key="componentKey" v-if="componentKey" />
|
||||||
|
|||||||
@@ -11635,7 +11635,7 @@ a.navbar-item.is-active, a.navbar-item.is-selected,
|
|||||||
margin: 0.5rem 0;
|
margin: 0.5rem 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media screen and (max-width: 1023px) {
|
@media screen and (max-width: 767px) {
|
||||||
.navbar > .container {
|
.navbar > .container {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
@@ -11684,7 +11684,7 @@ a.navbar-item.is-active, a.navbar-item.is-selected,
|
|||||||
padding-bottom: var(--bulma-navbar-height);
|
padding-bottom: var(--bulma-navbar-height);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@media screen and (min-width: 1024px) {
|
@media screen and (min-width: 768px) {
|
||||||
.navbar,
|
.navbar,
|
||||||
.navbar-menu,
|
.navbar-menu,
|
||||||
.navbar-start,
|
.navbar-start,
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -13,6 +13,7 @@ $grey: #767676;
|
|||||||
@use "bulma/sass" with (
|
@use "bulma/sass" with (
|
||||||
$family-primary: string.unquote("'Inter', 'SF Pro', 'Helvetica', 'Arial', sans-serif"),
|
$family-primary: string.unquote("'Inter', 'SF Pro', 'Helvetica', 'Arial', sans-serif"),
|
||||||
$family-monospace: string.unquote("'Roboto Mono', monospace"),
|
$family-monospace: string.unquote("'Roboto Mono', monospace"),
|
||||||
|
$navbar-breakpoint: 768px,
|
||||||
$primary: $blue,
|
$primary: $blue,
|
||||||
$link: $blue,
|
$link: $blue,
|
||||||
$info: $cyan,
|
$info: $cyan,
|
||||||
|
|||||||
Reference in New Issue
Block a user