Update to PrimeVue v4
This commit is contained in:
@@ -1,42 +0,0 @@
|
||||
.layout-config-button {
|
||||
display: block;
|
||||
position: fixed;
|
||||
width: 3rem;
|
||||
height: 3rem;
|
||||
line-height: 3rem;
|
||||
background: var(--primary-color);
|
||||
color: var(--primary-color-text);
|
||||
text-align: center;
|
||||
top: 50%;
|
||||
right: 0;
|
||||
margin-top: -1.5rem;
|
||||
border-top-left-radius: var(--border-radius);
|
||||
border-bottom-left-radius: var(--border-radius);
|
||||
border-top-right-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
transition: background-color var(--transition-duration);
|
||||
overflow: hidden;
|
||||
cursor: pointer;
|
||||
z-index: 999;
|
||||
box-shadow: -0.25rem 0 1rem rgba(0, 0, 0, 0.15);
|
||||
|
||||
i {
|
||||
font-size: 2rem;
|
||||
line-height: inherit;
|
||||
transform: rotate(0deg);
|
||||
transition: transform 1s;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background: var(--primary-400);
|
||||
}
|
||||
}
|
||||
|
||||
.layout-config-sidebar {
|
||||
&.p-sidebar {
|
||||
.p-sidebar-content {
|
||||
padding-left: 2rem;
|
||||
padding-right: 2rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -147,3 +147,62 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.config-panel {
|
||||
position: absolute;
|
||||
top: calc(100% + 2px);
|
||||
right: 0;
|
||||
width: 16rem;
|
||||
padding: .75rem;
|
||||
background-color: var(--overlay-background);
|
||||
border-radius: 6px;
|
||||
border: 1px solid var(--border-color);
|
||||
transform-origin: top;
|
||||
box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
|
||||
|
||||
.config-panel-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.config-panel-label {
|
||||
font-size: .875rem;
|
||||
color: var(--text-secondary-color);
|
||||
font-weight: 600;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.config-panel-colors {
|
||||
> div {
|
||||
padding-top: .5rem;
|
||||
display: flex;
|
||||
gap: .5rem;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
|
||||
button {
|
||||
border: none;
|
||||
width: 1.25rem;
|
||||
height: 1.25rem;
|
||||
border-radius: 50%;
|
||||
padding: 0;
|
||||
cursor: pointer;
|
||||
outline-color: transparent;
|
||||
outline-width: 2px;
|
||||
outline-style: solid;
|
||||
outline-offset: 1px;
|
||||
|
||||
&.active-color {
|
||||
outline-color: var(--primary-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.config-panel-settings {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,11 @@
|
||||
@import './_variables';
|
||||
@import "./_mixins";
|
||||
@import "./_preloading";
|
||||
@import "./_main";
|
||||
@import "./_topbar";
|
||||
@import "./_menu";
|
||||
@import "./_config";
|
||||
@import "./_content";
|
||||
@import "./_footer";
|
||||
@import "./_responsive";
|
||||
@import "./_utils";
|
||||
@import "./_typography";
|
||||
@import './_mixins';
|
||||
@import './_preloading';
|
||||
@import './_main';
|
||||
@import './_topbar';
|
||||
@import './_menu';
|
||||
@import './_content';
|
||||
@import './_footer';
|
||||
@import './_responsive';
|
||||
@import './_utils';
|
||||
@import './_typography';
|
||||
|
||||
@@ -1,12 +1,5 @@
|
||||
/* You can add global styles to this file, and also import other style files */
|
||||
|
||||
$gutter: 1rem; //for primeflex grid system
|
||||
@import '@/assets/layout/layout.scss';
|
||||
|
||||
/* PrimeVue */
|
||||
// @import 'primevue/resources/primevue.min.css'; // version deplicated. You must open the command line if you are using < 3.29.00
|
||||
@import 'primeflex/primeflex.scss';
|
||||
@import 'primeicons/primeicons.css';
|
||||
|
||||
/* Demos */
|
||||
@import '@/assets/demo/demo.scss';
|
||||
|
||||
|
||||
3
src/assets/tailwind.css
Normal file
3
src/assets/tailwind.css
Normal file
@@ -0,0 +1,3 @@
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
@@ -1,407 +0,0 @@
|
||||
<script setup>
|
||||
import { ref, computed } from 'vue';
|
||||
import { usePrimeVue } from 'primevue/config';
|
||||
import { useLayout } from '@/layout/composables/layout';
|
||||
|
||||
defineProps({
|
||||
simple: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
});
|
||||
|
||||
const $primevue = usePrimeVue();
|
||||
const inputStyle = computed(() => $primevue.config.inputStyle || 'outlined');
|
||||
|
||||
const scales = ref([12, 13, 14, 15, 16]);
|
||||
const visible = ref(false);
|
||||
const inputStyles = ref([
|
||||
{ label: 'Outlined', value: 'outlined' },
|
||||
{ label: 'Filled', value: 'filled' }
|
||||
]);
|
||||
const menuModes = ref([
|
||||
{ label: 'Static', value: 'static' },
|
||||
{ label: 'Overlay', value: 'overlay' }
|
||||
]);
|
||||
const compactMaterial = ref(false);
|
||||
const primaryFocusRing = ref(true);
|
||||
|
||||
const { setScale, layoutConfig } = useLayout();
|
||||
|
||||
const onConfigButtonClick = () => {
|
||||
visible.value = !visible.value;
|
||||
};
|
||||
const onChangeTheme = (theme, mode) => {
|
||||
$primevue.changeTheme(layoutConfig.theme.value, theme, 'theme-css', () => {
|
||||
layoutConfig.theme.value = theme;
|
||||
layoutConfig.darkTheme.value = mode;
|
||||
});
|
||||
};
|
||||
const decrementScale = () => {
|
||||
setScale(layoutConfig.scale.value - 1);
|
||||
applyScale();
|
||||
};
|
||||
const incrementScale = () => {
|
||||
setScale(layoutConfig.scale.value + 1);
|
||||
applyScale();
|
||||
};
|
||||
const applyScale = () => {
|
||||
document.documentElement.style.fontSize = layoutConfig.scale.value + 'px';
|
||||
};
|
||||
const onInputStyleChange = (value) => {
|
||||
$primevue.config.inputStyle = value;
|
||||
};
|
||||
const onMenuModeChange = (value) => {
|
||||
layoutConfig.menuMode.value = value;
|
||||
};
|
||||
const onRippleChange = (value) => {
|
||||
layoutConfig.ripple.value = value;
|
||||
};
|
||||
const onDarkModeChange = (value) => {
|
||||
const newThemeName = value ? layoutConfig.theme.value.replace('light', 'dark') : layoutConfig.theme.value.replace('dark', 'light');
|
||||
|
||||
layoutConfig.darkTheme.value = value;
|
||||
onChangeTheme(newThemeName, value);
|
||||
};
|
||||
const changeTheme = (theme, color) => {
|
||||
let newTheme, dark;
|
||||
|
||||
newTheme = theme + '-' + (layoutConfig.darkTheme.value ? 'dark' : 'light');
|
||||
|
||||
if (color) {
|
||||
newTheme += '-' + color;
|
||||
}
|
||||
|
||||
if (newTheme.startsWith('md-') && compactMaterial.value) {
|
||||
newTheme = newTheme.replace('md-', 'mdc-');
|
||||
}
|
||||
|
||||
dark = layoutConfig.darkTheme.value;
|
||||
|
||||
onChangeTheme(newTheme, dark);
|
||||
};
|
||||
const isThemeActive = (themeFamily, color) => {
|
||||
let themeName;
|
||||
let themePrefix = themeFamily === 'md' && compactMaterial.value ? 'mdc' : themeFamily;
|
||||
|
||||
themeName = themePrefix + (layoutConfig.darkTheme.value ? '-dark' : '-light');
|
||||
|
||||
if (color) {
|
||||
themeName += '-' + color;
|
||||
}
|
||||
|
||||
return layoutConfig.theme.value === themeName;
|
||||
};
|
||||
const onCompactMaterialChange = (value) => {
|
||||
compactMaterial.value = value;
|
||||
|
||||
if (layoutConfig.theme.value.startsWith('md')) {
|
||||
let tokens = layoutConfig.theme.value.split('-');
|
||||
|
||||
changeTheme(tokens[0].substring(0, 2), tokens[2]);
|
||||
}
|
||||
};
|
||||
const onFocusRingColorChange = (value) => {
|
||||
primaryFocusRing.value = value;
|
||||
let root = document.documentElement;
|
||||
|
||||
if (value) {
|
||||
if (layoutConfig.darkTheme.value) root.style.setProperty('--p-focus-ring-color', 'var(--primary-500)');
|
||||
else root.style.setProperty('--p-focus-ring-color', 'var(--primary-500)');
|
||||
} else {
|
||||
if (layoutConfig.darkTheme.value) root.style.setProperty('--p-focus-ring-color', 'var(--surface-500)');
|
||||
else root.style.setProperty('--p-focus-ring-color', 'var(--surface-900)');
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<button class="layout-config-button p-link" type="button" @click="onConfigButtonClick()">
|
||||
<i class="pi pi-cog"></i>
|
||||
</button>
|
||||
|
||||
<Sidebar v-model:visible="visible" position="right" class="layout-config-sidebar w-26rem" pt:closeButton="ml-auto">
|
||||
<div class="p-2">
|
||||
<section class="pb-4 flex align-items-center justify-content-between border-bottom-1 surface-border">
|
||||
<span class="text-xl font-semibold">Scale</span>
|
||||
<div class="flex align-items-center gap-2 border-1 surface-border py-1 px-2" style="border-radius: 30px">
|
||||
<Button icon="pi pi-minus" @click="decrementScale" text rounded :disabled="layoutConfig.scale.value === scales[0]" />
|
||||
<i v-for="s in scales" :key="s" :class="['pi pi-circle-fill text-sm text-200', { 'text-lg text-primary': s === layoutConfig.scale.value }]" />
|
||||
|
||||
<Button icon="pi pi-plus" @click="incrementScale" text rounded :disabled="layoutConfig.scale.value === scales[scales.length - 1]" />
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="py-4 flex align-items-center justify-content-between border-bottom-1 surface-border">
|
||||
<span :class="['text-xl font-semibold']">Dark Mode</span>
|
||||
<InputSwitch :modelValue="layoutConfig.darkTheme.value" @update:modelValue="onDarkModeChange" />
|
||||
</section>
|
||||
|
||||
<template v-if="!simple">
|
||||
<section class="py-4 flex align-items-center justify-content-between border-bottom-1 surface-border">
|
||||
<span class="text-xl font-semibold">Menu Type</span>
|
||||
<SelectButton :modelValue="layoutConfig.menuMode.value" @update:modelValue="onMenuModeChange" :options="menuModes" optionLabel="label" optionValue="value" :allowEmpty="false" />
|
||||
</section>
|
||||
|
||||
<section class="py-4 flex align-items-center justify-content-between border-bottom-1 surface-border">
|
||||
<span class="text-xl font-semibold">Input Variant</span>
|
||||
<SelectButton :modelValue="inputStyle" @update:modelValue="onInputStyleChange" :options="inputStyles" optionLabel="label" optionValue="value" :allowEmpty="false" />
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<section class="py-4 flex align-items-center justify-content-between border-bottom-1 surface-border">
|
||||
<span class="text-xl font-semibold">Ripple Effect</span>
|
||||
<InputSwitch :modelValue="layoutConfig.ripple.value" @update:modelValue="onRippleChange" />
|
||||
</section>
|
||||
|
||||
<section class="py-4 border-bottom-1 surface-border">
|
||||
<div class="text-xl font-semibold mb-3">Themes</div>
|
||||
<div class="flex align-items-center gap-2 mb-3">
|
||||
<img src="https://primefaces.org/cdn/primevue/images/themes/aura.png" alt="Aura" style="width: 1.5rem" />
|
||||
<span class="font-medium">Aura</span>
|
||||
</div>
|
||||
<div class="flex align-items-center justify-content-between gap-3 mb-3">
|
||||
<button
|
||||
:class="[
|
||||
'bg-transparent border-1 cursor-pointer p-2 w-3 flex align-items-center justify-content-center transition-all transition-duration-200',
|
||||
{ 'border-primary': isThemeActive('aura', 'green'), 'hover:border-500 surface-border': !isThemeActive('aura', 'green') }
|
||||
]"
|
||||
style="border-radius: 30px"
|
||||
@click="changeTheme('aura', 'green')"
|
||||
>
|
||||
<span class="block h-1rem w-full" style="border-radius: 30px; background: linear-gradient(180deg, #4dac9c 0%, rgba(77, 172, 156, 0.5) 100%)"></span>
|
||||
</button>
|
||||
<button
|
||||
:class="[
|
||||
'bg-transparent border-1 cursor-pointer p-2 w-3 flex align-items-center justify-content-center transition-all transition-duration-200',
|
||||
{ 'border-primary': isThemeActive('aura', 'cyan'), 'hover:border-500 surface-border': !isThemeActive('aura', 'cyan') }
|
||||
]"
|
||||
style="border-radius: 30px"
|
||||
@click="changeTheme('aura', 'cyan')"
|
||||
>
|
||||
<span class="block h-1rem w-full" style="border-radius: 30px; background: linear-gradient(180deg, #06b6d4 0%, rgba(6, 182, 212, 0.5) 100%)"></span>
|
||||
</button>
|
||||
<button
|
||||
:class="[
|
||||
'bg-transparent border-1 cursor-pointer p-2 w-3 flex align-items-center justify-content-center transition-all transition-duration-200',
|
||||
{ 'border-primary': isThemeActive('aura', 'blue'), 'hover:border-500 surface-border': !isThemeActive('aura', 'blue') }
|
||||
]"
|
||||
style="border-radius: 30px"
|
||||
@click="changeTheme('aura', 'blue')"
|
||||
>
|
||||
<span class="block h-1rem w-full" style="border-radius: 30px; background: linear-gradient(180deg, #4378e6 0%, rgba(67, 120, 230, 0.5) 100%)"></span>
|
||||
</button>
|
||||
<button
|
||||
:class="[
|
||||
'bg-transparent border-1 cursor-pointer p-2 w-3 flex align-items-center justify-content-center transition-all transition-duration-200',
|
||||
{ 'border-primary': isThemeActive('aura', 'indigo'), 'hover:border-500 surface-border': !isThemeActive('aura', 'indigo') }
|
||||
]"
|
||||
style="border-radius: 30px"
|
||||
@click="changeTheme('aura', 'indigo')"
|
||||
>
|
||||
<span class="block h-1rem w-full" style="border-radius: 30px; background: linear-gradient(180deg, #585fe0 0%, rgba(88, 95, 224, 0.5) 100%)"></span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="flex align-items-center justify-content-between gap-3 mb-3">
|
||||
<button
|
||||
:class="[
|
||||
'bg-transparent border-1 cursor-pointer p-2 w-3 flex align-items-center justify-content-center transition-all transition-duration-200',
|
||||
{ 'border-primary': isThemeActive('aura', 'purple'), 'hover:border-500 surface-border': !isThemeActive('aura', 'purple') }
|
||||
]"
|
||||
style="border-radius: 30px"
|
||||
@click="changeTheme('aura', 'purple')"
|
||||
>
|
||||
<span class="block h-1rem w-full" style="border-radius: 30px; background: linear-gradient(180deg, #7758e4 0%, rgba(119, 88, 228, 0.5) 100%)"></span>
|
||||
</button>
|
||||
<button
|
||||
:class="[
|
||||
'bg-transparent border-1 cursor-pointer p-2 w-3 flex align-items-center justify-content-center transition-all transition-duration-200',
|
||||
{ 'border-primary': isThemeActive('aura', 'amber'), 'hover:border-500 surface-border': !isThemeActive('aura', 'amber') }
|
||||
]"
|
||||
style="border-radius: 30px"
|
||||
@click="changeTheme('aura', 'amber')"
|
||||
>
|
||||
<span class="block h-1rem w-full" style="border-radius: 30px; background: linear-gradient(180deg, #f59e0b 0%, rgba(245, 158, 11, 0.5) 100%)"></span>
|
||||
</button>
|
||||
<button
|
||||
:class="[
|
||||
'bg-transparent border-1 cursor-pointer p-2 w-3 flex align-items-center justify-content-center transition-all transition-duration-200',
|
||||
{ 'border-primary': isThemeActive('aura', 'teal'), 'hover:border-500 surface-border': !isThemeActive('aura', 'teal') }
|
||||
]"
|
||||
style="border-radius: 30px"
|
||||
@click="changeTheme('aura', 'teal')"
|
||||
>
|
||||
<span class="block h-1rem w-full" style="border-radius: 30px; background: linear-gradient(180deg, #14b8a6 0%, rgba(20, 184, 166, 0.5) 100%)"></span>
|
||||
</button>
|
||||
<button
|
||||
:class="[
|
||||
'bg-transparent border-1 cursor-pointer p-2 w-3 flex align-items-center justify-content-center transition-all transition-duration-200',
|
||||
{ 'border-primary': isThemeActive('aura', 'pink'), 'hover:border-500 surface-border': !isThemeActive('aura', 'pink') }
|
||||
]"
|
||||
style="border-radius: 30px"
|
||||
@click="changeTheme('aura', 'pink')"
|
||||
>
|
||||
<span class="block h-1rem w-full" style="border-radius: 30px; background: linear-gradient(180deg, #ec4899 0%, rgba(236, 72, 153, 0.5) 100%)"></span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="flex align-items-center justify-content-between gap-3">
|
||||
<button
|
||||
:class="[
|
||||
'bg-transparent border-1 cursor-pointer p-2 w-3 flex align-items-center justify-content-center transition-all transition-duration-200',
|
||||
{ 'border-primary': isThemeActive('aura', 'noir'), 'hover:border-500 surface-border': !isThemeActive('aura', 'noir') }
|
||||
]"
|
||||
style="border-radius: 30px"
|
||||
@click="changeTheme('aura', 'noir')"
|
||||
>
|
||||
<span class="block h-1rem w-full" style="border-radius: 30px; background: linear-gradient(180deg, #0f172a 0%, rgba(0, 0, 0, 0.5) 100%)"></span>
|
||||
</button>
|
||||
<button
|
||||
:class="[
|
||||
'bg-transparent border-1 cursor-pointer p-2 w-3 flex align-items-center justify-content-center transition-all transition-duration-200',
|
||||
{ 'border-primary': isThemeActive('aura', 'lime'), 'hover:border-500 surface-border': !isThemeActive('aura', 'lime') }
|
||||
]"
|
||||
style="border-radius: 30px"
|
||||
@click="changeTheme('aura', 'lime')"
|
||||
>
|
||||
<span class="block h-1rem w-full" style="border-radius: 30px; background: linear-gradient(180deg, #84cc16 0%, rgb(132, 204, 22, 0.5) 100%)"></span>
|
||||
</button>
|
||||
<span class="w-3"></span>
|
||||
<span class="w-3"></span>
|
||||
</div>
|
||||
|
||||
<section class="pt-4 flex align-items-center justify-content-between">
|
||||
<span class="text-sm">Primary Focus Ring</span>
|
||||
<InputSwitch :modelValue="primaryFocusRing" @update:modelValue="onFocusRingColorChange" />
|
||||
</section>
|
||||
</section>
|
||||
|
||||
<section class="py-4 border-bottom-1 surface-border">
|
||||
<div class="flex align-items-center gap-2 mb-3">
|
||||
<img src="https://primefaces.org/cdn/primevue/images/themes/lara-light-teal.png" alt="Lara Light Teal" class="border-circle" style="width: 1.5rem" />
|
||||
<span class="font-medium">Lara</span>
|
||||
</div>
|
||||
<div class="flex align-items-center justify-content-between gap-3 mb-3">
|
||||
<button
|
||||
:class="[
|
||||
'bg-transparent border-1 cursor-pointer p-2 w-3 flex align-items-center justify-content-center transition-all transition-duration-200',
|
||||
{ 'border-primary': isThemeActive('lara', 'green'), 'hover:border-500 surface-border': !isThemeActive('lara', 'green') }
|
||||
]"
|
||||
style="border-radius: 30px"
|
||||
@click="changeTheme('lara', 'green')"
|
||||
>
|
||||
<span class="block h-1rem w-full" style="border-radius: 30px; background: linear-gradient(180deg, #4dac9c 0%, rgba(77, 172, 156, 0.5) 100%)"></span>
|
||||
</button>
|
||||
<button
|
||||
:class="[
|
||||
'bg-transparent border-1 cursor-pointer p-2 w-3 flex align-items-center justify-content-center transition-all transition-duration-200',
|
||||
{ 'border-primary': isThemeActive('lara', 'cyan'), 'hover:border-500 surface-border': !isThemeActive('lara', 'cyan') }
|
||||
]"
|
||||
style="border-radius: 30px"
|
||||
@click="changeTheme('lara', 'cyan')"
|
||||
>
|
||||
<span class="block h-1rem w-full" style="border-radius: 30px; background: linear-gradient(180deg, #06b6d4 0%, rgba(6, 182, 212, 0.5) 100%)"></span>
|
||||
</button>
|
||||
<button
|
||||
:class="[
|
||||
'bg-transparent border-1 cursor-pointer p-2 w-3 flex align-items-center justify-content-center transition-all transition-duration-200',
|
||||
{ 'border-primary': isThemeActive('lara', 'blue'), 'hover:border-500 surface-border': !isThemeActive('lara', 'blue') }
|
||||
]"
|
||||
style="border-radius: 30px"
|
||||
@click="changeTheme('lara', 'blue')"
|
||||
>
|
||||
<span class="block h-1rem w-full" style="border-radius: 30px; background: linear-gradient(180deg, #4378e6 0%, rgba(67, 120, 230, 0.5) 100%)"></span>
|
||||
</button>
|
||||
<button
|
||||
:class="[
|
||||
'bg-transparent border-1 cursor-pointer p-2 w-3 flex align-items-center justify-content-center transition-all transition-duration-200',
|
||||
{ 'border-primary': isThemeActive('lara', 'indigo'), 'hover:border-500 surface-border': !isThemeActive('lara', 'indigo') }
|
||||
]"
|
||||
style="border-radius: 30px"
|
||||
@click="changeTheme('lara', 'indigo')"
|
||||
>
|
||||
<span class="block h-1rem w-full" style="border-radius: 30px; background: linear-gradient(180deg, #585fe0 0%, rgba(88, 95, 224, 0.5) 100%)"></span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="flex align-items-center justify-content-between gap-3">
|
||||
<button
|
||||
:class="[
|
||||
'bg-transparent border-1 cursor-pointer p-2 w-3 flex align-items-center justify-content-center transition-all transition-duration-200',
|
||||
{ 'border-primary': isThemeActive('lara', 'purple'), 'hover:border-500 surface-border': !isThemeActive('lara', 'purple') }
|
||||
]"
|
||||
style="border-radius: 30px"
|
||||
@click="changeTheme('lara', 'purple')"
|
||||
>
|
||||
<span class="block h-1rem w-full" style="border-radius: 30px; background: linear-gradient(180deg, #7758e4 0%, rgba(119, 88, 228, 0.5) 100%)"></span>
|
||||
</button>
|
||||
<button
|
||||
:class="[
|
||||
'bg-transparent border-1 cursor-pointer p-2 w-3 flex align-items-center justify-content-center transition-all transition-duration-200',
|
||||
{ 'border-primary': isThemeActive('lara', 'amber'), 'hover:border-500 surface-border': !isThemeActive('lara', 'amber') }
|
||||
]"
|
||||
style="border-radius: 30px"
|
||||
@click="changeTheme('lara', 'amber')"
|
||||
>
|
||||
<span class="block h-1rem w-full" style="border-radius: 30px; background: linear-gradient(180deg, #f59e0b 0%, rgba(245, 158, 11, 0.5) 100%)"></span>
|
||||
</button>
|
||||
<button
|
||||
:class="[
|
||||
'bg-transparent border-1 cursor-pointer p-2 w-3 flex align-items-center justify-content-center transition-all transition-duration-200',
|
||||
{ 'border-primary': isThemeActive('lara', 'teal'), 'hover:border-500 surface-border': !isThemeActive('lara', 'teal') }
|
||||
]"
|
||||
style="border-radius: 30px"
|
||||
@click="changeTheme('lara', 'teal')"
|
||||
>
|
||||
<span class="block h-1rem w-full" style="border-radius: 30px; background: linear-gradient(180deg, #14b8a6 0%, rgba(20, 184, 166, 0.5) 100%)"></span>
|
||||
</button>
|
||||
<button
|
||||
:class="[
|
||||
'bg-transparent border-1 cursor-pointer p-2 w-3 flex align-items-center justify-content-center transition-all transition-duration-200',
|
||||
{ 'border-primary': isThemeActive('lara', 'pink'), 'hover:border-500 surface-border': !isThemeActive('lara', 'pink') }
|
||||
]"
|
||||
style="border-radius: 30px"
|
||||
@click="changeTheme('lara', 'pink')"
|
||||
>
|
||||
<span class="block h-1rem w-full" style="border-radius: 30px; background: linear-gradient(180deg, #ec4899 0%, rgba(236, 72, 153, 0.5) 100%)"></span>
|
||||
</button>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="py-4 border-bottom-1 surface-border">
|
||||
<div class="flex align-items-center gap-2 mb-3">
|
||||
<img src="https://primefaces.org/cdn/primevue/images/themes/md-light-indigo.svg" alt="Material Design" class="border-circle" style="width: 1.5rem" />
|
||||
<span class="font-medium">Material Design</span>
|
||||
<div class="ml-auto flex align-items-center gap-2">
|
||||
<label for="material-condensed" class="text-sm">Condensed</label>
|
||||
<InputSwitch inputId="material-condensed" :modelValue="compactMaterial" @update:modelValue="onCompactMaterialChange" class="ml-auto" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex align-items-center justify-content-between gap-3">
|
||||
<button
|
||||
:class="[
|
||||
'bg-transparent border-1 cursor-pointer p-2 w-3 flex align-items-center justify-content-center transition-all transition-duration-200',
|
||||
{ 'border-primary': isThemeActive('md', 'indigo'), 'hover:border-500 surface-border': !isThemeActive('md', 'indigo') }
|
||||
]"
|
||||
style="border-radius: 30px"
|
||||
@click="changeTheme('md', 'indigo')"
|
||||
>
|
||||
<span class="block h-1rem w-full" style="border-radius: 30px; background: linear-gradient(180deg, #0565f2 0%, rgba(5, 101, 242, 0.5) 100%)"></span>
|
||||
</button>
|
||||
<button
|
||||
:class="[
|
||||
'bg-transparent border-1 cursor-pointer p-2 w-3 flex align-items-center justify-content-center transition-all transition-duration-200',
|
||||
{ 'border-primary': isThemeActive('md', 'deeppurple'), 'hover:border-500 surface-border': !isThemeActive('md', 'deeppurple') }
|
||||
]"
|
||||
style="border-radius: 30px"
|
||||
@click="changeTheme('md', 'deeppurple')"
|
||||
>
|
||||
<span class="block h-1rem w-full" style="border-radius: 30px; background: linear-gradient(180deg, #702f92 0%, rgba(112, 47, 146, 0.5) 100%)"></span>
|
||||
</button>
|
||||
<div class="w-3"></div>
|
||||
<div class="w-3"></div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</Sidebar>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
271
src/layout/AppConfigurator.vue
Normal file
271
src/layout/AppConfigurator.vue
Normal file
@@ -0,0 +1,271 @@
|
||||
<script setup>
|
||||
import { ref, computed } from 'vue';
|
||||
import { $t, updatePreset, updateSurfacePalette } from '@primevue/themes';
|
||||
import { useLayout } from '@/layout/composables/layout';
|
||||
import Aura from '@primevue/themes/aura';
|
||||
import Lara from '@primevue/themes/lara';
|
||||
import Nora from '@primevue/themes/nora';
|
||||
|
||||
const { layoutConfig, setPrimary, setSurface, setPreset, isDarkTheme } = useLayout();
|
||||
|
||||
const presets = {
|
||||
Aura,
|
||||
Lara,
|
||||
Nora
|
||||
};
|
||||
|
||||
const presetOptions = ref(Object.keys(presets));
|
||||
|
||||
const primaryColors = ref([
|
||||
{ name: 'noir', palette: {} },
|
||||
{ name: 'emerald', palette: { 50: '#ecfdf5', 100: '#d1fae5', 200: '#a7f3d0', 300: '#6ee7b7', 400: '#34d399', 500: '#10b981', 600: '#059669', 700: '#047857', 800: '#065f46', 900: '#064e3b', 950: '#022c22' } },
|
||||
{ name: 'green', palette: { 50: '#f0fdf4', 100: '#dcfce7', 200: '#bbf7d0', 300: '#86efac', 400: '#4ade80', 500: '#22c55e', 600: '#16a34a', 700: '#15803d', 800: '#166534', 900: '#14532d', 950: '#052e16' } },
|
||||
{ name: 'lime', palette: { 50: '#f7fee7', 100: '#ecfccb', 200: '#d9f99d', 300: '#bef264', 400: '#a3e635', 500: '#84cc16', 600: '#65a30d', 700: '#4d7c0f', 800: '#3f6212', 900: '#365314', 950: '#1a2e05' } },
|
||||
{ name: 'orange', palette: { 50: '#fff7ed', 100: '#ffedd5', 200: '#fed7aa', 300: '#fdba74', 400: '#fb923c', 500: '#f97316', 600: '#ea580c', 700: '#c2410c', 800: '#9a3412', 900: '#7c2d12', 950: '#431407' } },
|
||||
{ name: 'amber', palette: { 50: '#fffbeb', 100: '#fef3c7', 200: '#fde68a', 300: '#fcd34d', 400: '#fbbf24', 500: '#f59e0b', 600: '#d97706', 700: '#b45309', 800: '#92400e', 900: '#78350f', 950: '#451a03' } },
|
||||
{ name: 'yellow', palette: { 50: '#fefce8', 100: '#fef9c3', 200: '#fef08a', 300: '#fde047', 400: '#facc15', 500: '#eab308', 600: '#ca8a04', 700: '#a16207', 800: '#854d0e', 900: '#713f12', 950: '#422006' } },
|
||||
{ name: 'teal', palette: { 50: '#f0fdfa', 100: '#ccfbf1', 200: '#99f6e4', 300: '#5eead4', 400: '#2dd4bf', 500: '#14b8a6', 600: '#0d9488', 700: '#0f766e', 800: '#115e59', 900: '#134e4a', 950: '#042f2e' } },
|
||||
{ name: 'cyan', palette: { 50: '#ecfeff', 100: '#cffafe', 200: '#a5f3fc', 300: '#67e8f9', 400: '#22d3ee', 500: '#06b6d4', 600: '#0891b2', 700: '#0e7490', 800: '#155e75', 900: '#164e63', 950: '#083344' } },
|
||||
{ name: 'sky', palette: { 50: '#f0f9ff', 100: '#e0f2fe', 200: '#bae6fd', 300: '#7dd3fc', 400: '#38bdf8', 500: '#0ea5e9', 600: '#0284c7', 700: '#0369a1', 800: '#075985', 900: '#0c4a6e', 950: '#082f49' } },
|
||||
{ name: 'blue', palette: { 50: '#eff6ff', 100: '#dbeafe', 200: '#bfdbfe', 300: '#93c5fd', 400: '#60a5fa', 500: '#3b82f6', 600: '#2563eb', 700: '#1d4ed8', 800: '#1e40af', 900: '#1e3a8a', 950: '#172554' } },
|
||||
{ name: 'indigo', palette: { 50: '#eef2ff', 100: '#e0e7ff', 200: '#c7d2fe', 300: '#a5b4fc', 400: '#818cf8', 500: '#6366f1', 600: '#4f46e5', 700: '#4338ca', 800: '#3730a3', 900: '#312e81', 950: '#1e1b4b' } },
|
||||
{ name: 'violet', palette: { 50: '#f5f3ff', 100: '#ede9fe', 200: '#ddd6fe', 300: '#c4b5fd', 400: '#a78bfa', 500: '#8b5cf6', 600: '#7c3aed', 700: '#6d28d9', 800: '#5b21b6', 900: '#4c1d95', 950: '#2e1065' } },
|
||||
{ name: 'purple', palette: { 50: '#faf5ff', 100: '#f3e8ff', 200: '#e9d5ff', 300: '#d8b4fe', 400: '#c084fc', 500: '#a855f7', 600: '#9333ea', 700: '#7e22ce', 800: '#6b21a8', 900: '#581c87', 950: '#3b0764' } },
|
||||
{ name: 'fuchsia', palette: { 50: '#fdf4ff', 100: '#fae8ff', 200: '#f5d0fe', 300: '#f0abfc', 400: '#e879f9', 500: '#d946ef', 600: '#c026d3', 700: '#a21caf', 800: '#86198f', 900: '#701a75', 950: '#4a044e' } },
|
||||
{ name: 'pink', palette: { 50: '#fdf2f8', 100: '#fce7f3', 200: '#fbcfe8', 300: '#f9a8d4', 400: '#f472b6', 500: '#ec4899', 600: '#db2777', 700: '#be185d', 800: '#9d174d', 900: '#831843', 950: '#500724' } },
|
||||
{ name: 'rose', palette: { 50: '#fff1f2', 100: '#ffe4e6', 200: '#fecdd3', 300: '#fda4af', 400: '#fb7185', 500: '#f43f5e', 600: '#e11d48', 700: '#be123c', 800: '#9f1239', 900: '#881337', 950: '#4c0519' } }
|
||||
]);
|
||||
|
||||
const surfaces = ref([
|
||||
{
|
||||
name: 'slate',
|
||||
palette: { 0: '#ffffff', 50: '#f8fafc', 100: '#f1f5f9', 200: '#e2e8f0', 300: '#cbd5e1', 400: '#94a3b8', 500: '#64748b', 600: '#475569', 700: '#334155', 800: '#1e293b', 900: '#0f172a', 950: '#020617' }
|
||||
},
|
||||
{
|
||||
name: 'gray',
|
||||
palette: { 0: '#ffffff', 50: '#f9fafb', 100: '#f3f4f6', 200: '#e5e7eb', 300: '#d1d5db', 400: '#9ca3af', 500: '#6b7280', 600: '#4b5563', 700: '#374151', 800: '#1f2937', 900: '#111827', 950: '#030712' }
|
||||
},
|
||||
{
|
||||
name: 'zinc',
|
||||
palette: { 0: '#ffffff', 50: '#fafafa', 100: '#f4f4f5', 200: '#e4e4e7', 300: '#d4d4d8', 400: '#a1a1aa', 500: '#71717a', 600: '#52525b', 700: '#3f3f46', 800: '#27272a', 900: '#18181b', 950: '#09090b' }
|
||||
},
|
||||
{
|
||||
name: 'neutral',
|
||||
palette: { 0: '#ffffff', 50: '#fafafa', 100: '#f5f5f5', 200: '#e5e5e5', 300: '#d4d4d4', 400: '#a3a3a3', 500: '#737373', 600: '#525252', 700: '#404040', 800: '#262626', 900: '#171717', 950: '#0a0a0a' }
|
||||
},
|
||||
{
|
||||
name: 'stone',
|
||||
palette: { 0: '#ffffff', 50: '#fafaf9', 100: '#f5f5f4', 200: '#e7e5e4', 300: '#d6d3d1', 400: '#a8a29e', 500: '#78716c', 600: '#57534e', 700: '#44403c', 800: '#292524', 900: '#1c1917', 950: '#0c0a09' }
|
||||
},
|
||||
{
|
||||
name: 'soho',
|
||||
palette: { 0: '#ffffff', 50: '#f4f4f4', 100: '#e8e9e9', 200: '#d2d2d4', 300: '#bbbcbe', 400: '#a5a5a9', 500: '#8e8f93', 600: '#77787d', 700: '#616268', 800: '#4a4b52', 900: '#34343d', 950: '#1d1e27' }
|
||||
},
|
||||
{
|
||||
name: 'viva',
|
||||
palette: { 0: '#ffffff', 50: '#f3f3f3', 100: '#e7e7e8', 200: '#cfd0d0', 300: '#b7b8b9', 400: '#9fa1a1', 500: '#87898a', 600: '#6e7173', 700: '#565a5b', 800: '#3e4244', 900: '#262b2c', 950: '#0e1315' }
|
||||
},
|
||||
{
|
||||
name: 'ocean',
|
||||
palette: { 0: '#ffffff', 50: '#fbfcfc', 100: '#F7F9F8', 200: '#EFF3F2', 300: '#DADEDD', 400: '#B1B7B6', 500: '#828787', 600: '#5F7274', 700: '#415B61', 800: '#29444E', 900: '#183240', 950: '#0c1920' }
|
||||
}
|
||||
]);
|
||||
|
||||
function getPresetExt() {
|
||||
const color = primaryColors.value.find((c) => c.name === layoutConfig.primary.value);
|
||||
|
||||
if (color.name === 'noir') {
|
||||
return {
|
||||
semantic: {
|
||||
primary: {
|
||||
50: '{surface.50}',
|
||||
100: '{surface.100}',
|
||||
200: '{surface.200}',
|
||||
300: '{surface.300}',
|
||||
400: '{surface.400}',
|
||||
500: '{surface.500}',
|
||||
600: '{surface.600}',
|
||||
700: '{surface.700}',
|
||||
800: '{surface.800}',
|
||||
900: '{surface.900}',
|
||||
950: '{surface.950}'
|
||||
},
|
||||
colorScheme: {
|
||||
light: {
|
||||
primary: {
|
||||
color: '{primary.950}',
|
||||
contrastColor: '#ffffff',
|
||||
hoverColor: '{primary.800}',
|
||||
activeColor: '{primary.700}'
|
||||
},
|
||||
highlight: {
|
||||
background: '{primary.950}',
|
||||
focusBackground: '{primary.700}',
|
||||
color: '#ffffff',
|
||||
focusColor: '#ffffff'
|
||||
}
|
||||
},
|
||||
dark: {
|
||||
primary: {
|
||||
color: '{primary.50}',
|
||||
contrastColor: '{primary.950}',
|
||||
hoverColor: '{primary.200}',
|
||||
activeColor: '{primary.300}'
|
||||
},
|
||||
highlight: {
|
||||
background: '{primary.50}',
|
||||
focusBackground: '{primary.300}',
|
||||
color: '{primary.950}',
|
||||
focusColor: '{primary.950}'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
} else {
|
||||
if (layoutConfig.preset === 'Nora') {
|
||||
return {
|
||||
semantic: {
|
||||
primary: color.palette,
|
||||
colorScheme: {
|
||||
light: {
|
||||
primary: {
|
||||
color: '{primary.600}',
|
||||
contrastColor: '#ffffff',
|
||||
hoverColor: '{primary.700}',
|
||||
activeColor: '{primary.800}'
|
||||
},
|
||||
highlight: {
|
||||
background: '{primary.600}',
|
||||
focusBackground: '{primary.700}',
|
||||
color: '#ffffff',
|
||||
focusColor: '#ffffff'
|
||||
}
|
||||
},
|
||||
dark: {
|
||||
primary: {
|
||||
color: '{primary.500}',
|
||||
contrastColor: '{surface.900}',
|
||||
hoverColor: '{primary.400}',
|
||||
activeColor: '{primary.300}'
|
||||
},
|
||||
highlight: {
|
||||
background: '{primary.500}',
|
||||
focusBackground: '{primary.400}',
|
||||
color: '{surface.900}',
|
||||
focusColor: '{surface.900}'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
semantic: {
|
||||
primary: color.palette,
|
||||
colorScheme: {
|
||||
light: {
|
||||
primary: {
|
||||
color: '{primary.500}',
|
||||
contrastColor: '#ffffff',
|
||||
hoverColor: '{primary.600}',
|
||||
activeColor: '{primary.700}'
|
||||
},
|
||||
highlight: {
|
||||
background: '{primary.50}',
|
||||
focusBackground: '{primary.100}',
|
||||
color: '{primary.700}',
|
||||
focusColor: '{primary.800}'
|
||||
}
|
||||
},
|
||||
dark: {
|
||||
primary: {
|
||||
color: '{primary.400}',
|
||||
contrastColor: '{surface.900}',
|
||||
hoverColor: '{primary.300}',
|
||||
activeColor: '{primary.200}'
|
||||
},
|
||||
highlight: {
|
||||
background: 'color-mix(in srgb, {primary.400}, transparent 84%)',
|
||||
focusBackground: 'color-mix(in srgb, {primary.400}, transparent 76%)',
|
||||
color: 'rgba(255,255,255,.87)',
|
||||
focusColor: 'rgba(255,255,255,.87)'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function updateColors(type, color) {
|
||||
if (type === 'primary') {
|
||||
setPrimary(color.name);
|
||||
} else if (type === 'surface') {
|
||||
setSurface(color.name);
|
||||
}
|
||||
|
||||
applyTheme(type, color);
|
||||
}
|
||||
|
||||
function applyTheme(type, color) {
|
||||
if (type === 'primary') {
|
||||
updatePreset(getPresetExt());
|
||||
} else if (type === 'surface') {
|
||||
updateSurfacePalette(color.palette);
|
||||
}
|
||||
|
||||
/*EventBus.emit('theme-palette-change');*/
|
||||
}
|
||||
|
||||
function onPresetChange(value) {
|
||||
setPreset(value);
|
||||
const preset = presetOptions[value];
|
||||
const surfacePalette = surfaces.value.find((s) => s.name === selectedSurfaceColor.value)?.palette;
|
||||
|
||||
$t().preset(preset).preset(getPresetExt()).surfacePalette(surfacePalette).use({ useDefaultOptions: true });
|
||||
}
|
||||
|
||||
const selectedPrimaryColor = computed(() => {
|
||||
return layoutConfig.primary.value;
|
||||
});
|
||||
|
||||
const selectedSurfaceColor = computed(() => {
|
||||
return layoutConfig.surface.value;
|
||||
});
|
||||
|
||||
const preset = computed(() => {
|
||||
return layoutConfig.preset;
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="config-panel hidden">
|
||||
<div class="config-panel-content">
|
||||
<div class="config-panel-colors">
|
||||
<span class="config-panel-label">Primary</span>
|
||||
<div>
|
||||
<button v-for="primaryColor of primaryColors" :key="primaryColor.name" type="button"
|
||||
:title="primaryColor.name" @click="updateColors('primary', primaryColor)"
|
||||
:class="{ 'active-color': selectedPrimaryColor === primaryColor.name }"
|
||||
:style="{ backgroundColor: `${primaryColor.name === 'noir' ? 'var(--text-color)' : primaryColor.palette['500']}` }"></button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="config-panel-colors">
|
||||
<span class="config-panel-label">Surface</span>
|
||||
<div>
|
||||
<button v-for="surface of surfaces" :key="surface.name" type="button" :title="surface.name"
|
||||
@click="updateColors('surface', surface)"
|
||||
:class="{ 'active-color': selectedSurfaceColor ? selectedSurfaceColor === surface.name : isDarkTheme ? surface.name === 'zinc' : surface.name === 'slate' }"
|
||||
:style="{ backgroundColor: `${surface.palette['500']}` }"></button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="config-panel-settings">
|
||||
<span class="config-panel-label">Presets</span>
|
||||
<SelectButton v-model="preset" @update:modelValue="onPresetChange" :options="presetOptions"
|
||||
:allowEmpty="false" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -3,7 +3,6 @@ import { computed, watch, ref } from 'vue';
|
||||
import AppTopbar from './AppTopbar.vue';
|
||||
import AppFooter from './AppFooter.vue';
|
||||
import AppSidebar from './AppSidebar.vue';
|
||||
import AppConfig from './AppConfig.vue';
|
||||
import { useLayout } from '@/layout/composables/layout';
|
||||
|
||||
const { layoutConfig, layoutState, isSidebarActive } = useLayout();
|
||||
@@ -68,7 +67,6 @@ const isOutsideClicked = (event) => {
|
||||
</div>
|
||||
<app-footer></app-footer>
|
||||
</div>
|
||||
<app-config></app-config>
|
||||
<div class="layout-mask"></div>
|
||||
</div>
|
||||
<Toast />
|
||||
|
||||
@@ -2,8 +2,9 @@
|
||||
import { ref, computed, onMounted, onBeforeUnmount } from 'vue';
|
||||
import { useLayout } from '@/layout/composables/layout';
|
||||
import { useRouter } from 'vue-router';
|
||||
import AppConfigurator from './AppConfigurator.vue';
|
||||
|
||||
const { layoutConfig, onMenuToggle } = useLayout();
|
||||
const { layoutConfig, onMenuToggle, toggleDarkMode, isDarkTheme } = useLayout();
|
||||
|
||||
const outsideClickListener = ref(null);
|
||||
const topbarMenuActive = ref(false);
|
||||
@@ -84,6 +85,17 @@ const isOutsideClicked = (event) => {
|
||||
<i class="pi pi-user"></i>
|
||||
<span>Profile</span>
|
||||
</button>
|
||||
<button type="button" class="p-link layout-topbar-button" @click="toggleDarkMode">
|
||||
<i :class="['pi', { 'pi-moon': isDarkTheme, 'pi-sun': !isDarkTheme }]"></i>
|
||||
</button>
|
||||
<div>
|
||||
<button
|
||||
v-styleclass="{ selector: '@next', enterFromClass: 'hidden', enterActiveClass: 'animate-scalein', leaveToClass: 'hidden', leaveActiveClass: 'animate-fadeout', hideOnOutsideClick: true }"
|
||||
type="button" class="p-link layout-topbar-button">
|
||||
<i class="pi pi-palette"></i>
|
||||
</button>
|
||||
<AppConfigurator />
|
||||
</div>
|
||||
<button @click="onSettingsClick()" class="p-link layout-topbar-button">
|
||||
<i class="pi pi-cog"></i>
|
||||
<span>Settings</span>
|
||||
|
||||
@@ -7,6 +7,9 @@ const layoutConfig = reactive({
|
||||
menuMode: 'static',
|
||||
theme: 'aura-light-green',
|
||||
scale: 14,
|
||||
primary: 'emerald',
|
||||
surface: null,
|
||||
preset: 'Aura',
|
||||
activeMenuItem: null
|
||||
});
|
||||
|
||||
@@ -44,5 +47,22 @@ export function useLayout() {
|
||||
|
||||
const isDarkTheme = computed(() => layoutConfig.darkTheme);
|
||||
|
||||
return { layoutConfig: toRefs(layoutConfig), layoutState: toRefs(layoutState), setScale, onMenuToggle, isSidebarActive, isDarkTheme, setActiveMenuItem };
|
||||
const toggleDarkMode = () => {
|
||||
layoutConfig.darkTheme = !layoutConfig.darkTheme;
|
||||
document.documentElement.classList.toggle('app-dark');
|
||||
};
|
||||
|
||||
const setPrimary = (value) => {
|
||||
layoutConfig.primary = value;
|
||||
};
|
||||
|
||||
const setSurface = (value) => {
|
||||
layoutConfig.surface = value;
|
||||
};
|
||||
|
||||
const setPreset = (value) => {
|
||||
layoutConfig.preset = value;
|
||||
};
|
||||
|
||||
return { layoutConfig: toRefs(layoutConfig), layoutState: toRefs(layoutState), setScale, onMenuToggle, isSidebarActive, isDarkTheme, setActiveMenuItem, toggleDarkMode, setPrimary, setSurface, setPreset };
|
||||
}
|
||||
|
||||
213
src/main.js
213
src/main.js
@@ -3,222 +3,27 @@ import App from './App.vue';
|
||||
import router from './router';
|
||||
|
||||
import PrimeVue from 'primevue/config';
|
||||
import AutoComplete from 'primevue/autocomplete';
|
||||
import Accordion from 'primevue/accordion';
|
||||
import AccordionTab from 'primevue/accordiontab';
|
||||
import Avatar from 'primevue/avatar';
|
||||
import AvatarGroup from 'primevue/avatargroup';
|
||||
import Badge from 'primevue/badge';
|
||||
import BadgeDirective from 'primevue/badgedirective';
|
||||
import BlockUI from 'primevue/blockui';
|
||||
import Button from 'primevue/button';
|
||||
import ButtonGroup from 'primevue/buttongroup';
|
||||
import Breadcrumb from 'primevue/breadcrumb';
|
||||
import Calendar from 'primevue/calendar';
|
||||
import Card from 'primevue/card';
|
||||
import Chart from 'primevue/chart';
|
||||
import CascadeSelect from 'primevue/cascadeselect';
|
||||
import Carousel from 'primevue/carousel';
|
||||
import Checkbox from 'primevue/checkbox';
|
||||
import Chip from 'primevue/chip';
|
||||
import Chips from 'primevue/chips';
|
||||
import ColorPicker from 'primevue/colorpicker';
|
||||
import Column from 'primevue/column';
|
||||
import ColumnGroup from 'primevue/columngroup';
|
||||
import ConfirmDialog from 'primevue/confirmdialog';
|
||||
import ConfirmPopup from 'primevue/confirmpopup';
|
||||
import ConfirmationService from 'primevue/confirmationservice';
|
||||
import ContextMenu from 'primevue/contextmenu';
|
||||
import DataTable from 'primevue/datatable';
|
||||
import DataView from 'primevue/dataview';
|
||||
import DataViewLayoutOptions from 'primevue/dataviewlayoutoptions';
|
||||
import DeferredContent from 'primevue/deferredcontent';
|
||||
import Dialog from 'primevue/dialog';
|
||||
import DialogService from 'primevue/dialogservice';
|
||||
import Divider from 'primevue/divider';
|
||||
import Dock from 'primevue/dock';
|
||||
import Dropdown from 'primevue/dropdown';
|
||||
import DynamicDialog from 'primevue/dynamicdialog';
|
||||
import Fieldset from 'primevue/fieldset';
|
||||
import FileUpload from 'primevue/fileupload';
|
||||
import FloatLabel from 'primevue/floatlabel';
|
||||
import Galleria from 'primevue/galleria';
|
||||
import IconField from 'primevue/iconfield';
|
||||
import Image from 'primevue/image';
|
||||
import InlineMessage from 'primevue/inlinemessage';
|
||||
import Inplace from 'primevue/inplace';
|
||||
import InputGroup from 'primevue/inputgroup';
|
||||
import InputGroupAddon from 'primevue/inputgroupaddon';
|
||||
import InputIcon from 'primevue/inputicon';
|
||||
import InputSwitch from 'primevue/inputswitch';
|
||||
import InputText from 'primevue/inputtext';
|
||||
import InputMask from 'primevue/inputmask';
|
||||
import InputNumber from 'primevue/inputnumber';
|
||||
import Knob from 'primevue/knob';
|
||||
import Listbox from 'primevue/listbox';
|
||||
import MegaMenu from 'primevue/megamenu';
|
||||
import Menu from 'primevue/menu';
|
||||
import Menubar from 'primevue/menubar';
|
||||
import Message from 'primevue/message';
|
||||
import MultiSelect from 'primevue/multiselect';
|
||||
import OrderList from 'primevue/orderlist';
|
||||
import OrganizationChart from 'primevue/organizationchart';
|
||||
import OverlayPanel from 'primevue/overlaypanel';
|
||||
import Paginator from 'primevue/paginator';
|
||||
import Panel from 'primevue/panel';
|
||||
import PanelMenu from 'primevue/panelmenu';
|
||||
import Password from 'primevue/password';
|
||||
import PickList from 'primevue/picklist';
|
||||
import ProgressBar from 'primevue/progressbar';
|
||||
import ProgressSpinner from 'primevue/progressspinner';
|
||||
import Rating from 'primevue/rating';
|
||||
import RadioButton from 'primevue/radiobutton';
|
||||
import Ripple from 'primevue/ripple';
|
||||
import Row from 'primevue/row';
|
||||
import SelectButton from 'primevue/selectbutton';
|
||||
import ScrollPanel from 'primevue/scrollpanel';
|
||||
import ScrollTop from 'primevue/scrolltop';
|
||||
import Skeleton from 'primevue/skeleton';
|
||||
import Slider from 'primevue/slider';
|
||||
import Sidebar from 'primevue/sidebar';
|
||||
import SpeedDial from 'primevue/speeddial';
|
||||
import SplitButton from 'primevue/splitbutton';
|
||||
import Splitter from 'primevue/splitter';
|
||||
import SplitterPanel from 'primevue/splitterpanel';
|
||||
import Steps from 'primevue/steps';
|
||||
import StyleClass from 'primevue/styleclass';
|
||||
import TabMenu from 'primevue/tabmenu';
|
||||
import TieredMenu from 'primevue/tieredmenu';
|
||||
import Textarea from 'primevue/textarea';
|
||||
import Toast from 'primevue/toast';
|
||||
import Aura from '@primevue/themes/aura';
|
||||
import ToastService from 'primevue/toastservice';
|
||||
import Toolbar from 'primevue/toolbar';
|
||||
import TabView from 'primevue/tabview';
|
||||
import TabPanel from 'primevue/tabpanel';
|
||||
import Tag from 'primevue/tag';
|
||||
import Terminal from 'primevue/terminal';
|
||||
import Timeline from 'primevue/timeline';
|
||||
import ToggleButton from 'primevue/togglebutton';
|
||||
import Tooltip from 'primevue/tooltip';
|
||||
import Tree from 'primevue/tree';
|
||||
import TreeSelect from 'primevue/treeselect';
|
||||
import TreeTable from 'primevue/treetable';
|
||||
import TriStateCheckbox from 'primevue/tristatecheckbox';
|
||||
import VirtualScroller from 'primevue/virtualscroller';
|
||||
import ConfirmationService from 'primevue/confirmationservice';
|
||||
|
||||
import BlockViewer from '@/components/BlockViewer.vue';
|
||||
|
||||
import '@/assets/styles.scss';
|
||||
import '@/assets/tailwind.css';
|
||||
|
||||
const app = createApp(App);
|
||||
|
||||
app.use(router);
|
||||
app.use(PrimeVue, { ripple: true });
|
||||
app.use(PrimeVue, {
|
||||
theme: {
|
||||
preset: Aura,
|
||||
darkModeSelector: 'app-dark'
|
||||
}
|
||||
});
|
||||
app.use(ToastService);
|
||||
app.use(DialogService);
|
||||
app.use(ConfirmationService);
|
||||
|
||||
app.directive('tooltip', Tooltip);
|
||||
app.directive('badge', BadgeDirective);
|
||||
app.directive('ripple', Ripple);
|
||||
app.directive('styleclass', StyleClass);
|
||||
|
||||
app.component('BlockViewer', BlockViewer);
|
||||
|
||||
app.component('Accordion', Accordion);
|
||||
app.component('AccordionTab', AccordionTab);
|
||||
app.component('AutoComplete', AutoComplete);
|
||||
app.component('Avatar', Avatar);
|
||||
app.component('AvatarGroup', AvatarGroup);
|
||||
app.component('Badge', Badge);
|
||||
app.component('BlockUI', BlockUI);
|
||||
app.component('Breadcrumb', Breadcrumb);
|
||||
app.component('Button', Button);
|
||||
app.component('ButtonGroup', ButtonGroup);
|
||||
app.component('Calendar', Calendar);
|
||||
app.component('Card', Card);
|
||||
app.component('Chart', Chart);
|
||||
app.component('Carousel', Carousel);
|
||||
app.component('CascadeSelect', CascadeSelect);
|
||||
app.component('Checkbox', Checkbox);
|
||||
app.component('Chip', Chip);
|
||||
app.component('Chips', Chips);
|
||||
app.component('ColorPicker', ColorPicker);
|
||||
app.component('Column', Column);
|
||||
app.component('ColumnGroup', ColumnGroup);
|
||||
app.component('ConfirmDialog', ConfirmDialog);
|
||||
app.component('ConfirmPopup', ConfirmPopup);
|
||||
app.component('ContextMenu', ContextMenu);
|
||||
app.component('DataTable', DataTable);
|
||||
app.component('DataView', DataView);
|
||||
app.component('DataViewLayoutOptions', DataViewLayoutOptions);
|
||||
app.component('DeferredContent', DeferredContent);
|
||||
app.component('Dialog', Dialog);
|
||||
app.component('Divider', Divider);
|
||||
app.component('Dock', Dock);
|
||||
app.component('Dropdown', Dropdown);
|
||||
app.component('DynamicDialog', DynamicDialog);
|
||||
app.component('Fieldset', Fieldset);
|
||||
app.component('FileUpload', FileUpload);
|
||||
app.component('FloatLabel', FloatLabel);
|
||||
app.component('Galleria', Galleria);
|
||||
app.component('IconField', IconField);
|
||||
app.component('Image', Image);
|
||||
app.component('InlineMessage', InlineMessage);
|
||||
app.component('Inplace', Inplace);
|
||||
app.component('InputGroup', InputGroup);
|
||||
app.component('InputGroupAddon', InputGroupAddon);
|
||||
app.component('InputIcon', InputIcon);
|
||||
app.component('InputMask', InputMask);
|
||||
app.component('InputNumber', InputNumber);
|
||||
app.component('InputSwitch', InputSwitch);
|
||||
app.component('InputText', InputText);
|
||||
app.component('Knob', Knob);
|
||||
app.component('Listbox', Listbox);
|
||||
app.component('MegaMenu', MegaMenu);
|
||||
app.component('Menu', Menu);
|
||||
app.component('Menubar', Menubar);
|
||||
app.component('Message', Message);
|
||||
app.component('MultiSelect', MultiSelect);
|
||||
app.component('OrderList', OrderList);
|
||||
app.component('OrganizationChart', OrganizationChart);
|
||||
app.component('OverlayPanel', OverlayPanel);
|
||||
app.component('Paginator', Paginator);
|
||||
app.component('Panel', Panel);
|
||||
app.component('PanelMenu', PanelMenu);
|
||||
app.component('Password', Password);
|
||||
app.component('PickList', PickList);
|
||||
app.component('ProgressBar', ProgressBar);
|
||||
app.component('ProgressSpinner', ProgressSpinner);
|
||||
app.component('RadioButton', RadioButton);
|
||||
app.component('Rating', Rating);
|
||||
app.component('Row', Row);
|
||||
app.component('SelectButton', SelectButton);
|
||||
app.component('ScrollPanel', ScrollPanel);
|
||||
app.component('ScrollTop', ScrollTop);
|
||||
app.component('Slider', Slider);
|
||||
app.component('Sidebar', Sidebar);
|
||||
app.component('Skeleton', Skeleton);
|
||||
app.component('SpeedDial', SpeedDial);
|
||||
app.component('SplitButton', SplitButton);
|
||||
app.component('Splitter', Splitter);
|
||||
app.component('SplitterPanel', SplitterPanel);
|
||||
app.component('Steps', Steps);
|
||||
app.component('TabMenu', TabMenu);
|
||||
app.component('TabView', TabView);
|
||||
app.component('TabPanel', TabPanel);
|
||||
app.component('Tag', Tag);
|
||||
app.component('Textarea', Textarea);
|
||||
app.component('Terminal', Terminal);
|
||||
app.component('TieredMenu', TieredMenu);
|
||||
app.component('Timeline', Timeline);
|
||||
app.component('Toast', Toast);
|
||||
app.component('Toolbar', Toolbar);
|
||||
app.component('ToggleButton', ToggleButton);
|
||||
app.component('Tree', Tree);
|
||||
app.component('TreeSelect', TreeSelect);
|
||||
app.component('TreeTable', TreeTable);
|
||||
app.component('TriStateCheckbox', TriStateCheckbox);
|
||||
app.component('VirtualScroller', VirtualScroller);
|
||||
|
||||
app.mount('#app');
|
||||
|
||||
@@ -123,7 +123,8 @@ watch(
|
||||
<span class="block text-500 font-medium mb-3">Orders</span>
|
||||
<div class="text-900 font-medium text-xl">152</div>
|
||||
</div>
|
||||
<div class="flex align-items-center justify-content-center bg-blue-100 border-round" style="width: 2.5rem; height: 2.5rem">
|
||||
<div class="flex align-items-center justify-content-center bg-blue-100 border-round"
|
||||
style="width: 2.5rem; height: 2.5rem">
|
||||
<i class="pi pi-shopping-cart text-blue-500 text-xl"></i>
|
||||
</div>
|
||||
</div>
|
||||
@@ -138,7 +139,8 @@ watch(
|
||||
<span class="block text-500 font-medium mb-3">Revenue</span>
|
||||
<div class="text-900 font-medium text-xl">$2.100</div>
|
||||
</div>
|
||||
<div class="flex align-items-center justify-content-center bg-orange-100 border-round" style="width: 2.5rem; height: 2.5rem">
|
||||
<div class="flex align-items-center justify-content-center bg-orange-100 border-round"
|
||||
style="width: 2.5rem; height: 2.5rem">
|
||||
<i class="pi pi-map-marker text-orange-500 text-xl"></i>
|
||||
</div>
|
||||
</div>
|
||||
@@ -153,7 +155,8 @@ watch(
|
||||
<span class="block text-500 font-medium mb-3">Customers</span>
|
||||
<div class="text-900 font-medium text-xl">28441</div>
|
||||
</div>
|
||||
<div class="flex align-items-center justify-content-center bg-cyan-100 border-round" style="width: 2.5rem; height: 2.5rem">
|
||||
<div class="flex align-items-center justify-content-center bg-cyan-100 border-round"
|
||||
style="width: 2.5rem; height: 2.5rem">
|
||||
<i class="pi pi-inbox text-cyan-500 text-xl"></i>
|
||||
</div>
|
||||
</div>
|
||||
@@ -168,7 +171,8 @@ watch(
|
||||
<span class="block text-500 font-medium mb-3">Comments</span>
|
||||
<div class="text-900 font-medium text-xl">152 Unread</div>
|
||||
</div>
|
||||
<div class="flex align-items-center justify-content-center bg-purple-100 border-round" style="width: 2.5rem; height: 2.5rem">
|
||||
<div class="flex align-items-center justify-content-center bg-purple-100 border-round"
|
||||
style="width: 2.5rem; height: 2.5rem">
|
||||
<i class="pi pi-comment text-purple-500 text-xl"></i>
|
||||
</div>
|
||||
</div>
|
||||
@@ -184,7 +188,8 @@ watch(
|
||||
<Column style="width: 15%">
|
||||
<template #header> Image </template>
|
||||
<template #body="slotProps">
|
||||
<img :src="'demo/images/product/' + slotProps.data.image" :alt="slotProps.data.image" width="50" class="shadow-2" />
|
||||
<img :src="'demo/images/product/' + slotProps.data.image" :alt="slotProps.data.image"
|
||||
width="50" class="shadow-2" />
|
||||
</template>
|
||||
</Column>
|
||||
<Column field="name" header="Name" :sortable="true" style="width: 35%"></Column>
|
||||
@@ -205,7 +210,8 @@ watch(
|
||||
<div class="flex justify-content-between align-items-center mb-5">
|
||||
<h5>Best Selling Products</h5>
|
||||
<div>
|
||||
<Button icon="pi pi-ellipsis-v" class="p-button-text p-button-plain p-button-rounded" @click="$refs.menu2.toggle($event)"></Button>
|
||||
<Button icon="pi pi-ellipsis-v" class="p-button-text p-button-plain p-button-rounded"
|
||||
@click="$refs.menu2.toggle($event)"></Button>
|
||||
<Menu ref="menu2" :popup="true" :model="items"></Menu>
|
||||
</div>
|
||||
</div>
|
||||
@@ -294,7 +300,8 @@ watch(
|
||||
<div class="flex align-items-center justify-content-between mb-4">
|
||||
<h5>Notifications</h5>
|
||||
<div>
|
||||
<Button icon="pi pi-ellipsis-v" class="p-button-text p-button-plain p-button-rounded" @click="$refs.menu1.toggle($event)"></Button>
|
||||
<Button icon="pi pi-ellipsis-v" class="p-button-text p-button-plain p-button-rounded"
|
||||
@click="$refs.menu1.toggle($event)"></Button>
|
||||
<Menu ref="menu1" :popup="true" :model="items"></Menu>
|
||||
</div>
|
||||
</div>
|
||||
@@ -302,54 +309,58 @@ watch(
|
||||
<span class="block text-600 font-medium mb-3">TODAY</span>
|
||||
<ul class="p-0 mx-0 mt-0 mb-4 list-none">
|
||||
<li class="flex align-items-center py-2 border-bottom-1 surface-border">
|
||||
<div class="w-3rem h-3rem flex align-items-center justify-content-center bg-blue-100 border-circle mr-3 flex-shrink-0">
|
||||
<div
|
||||
class="w-3rem h-3rem flex align-items-center justify-content-center bg-blue-100 border-circle mr-3 flex-shrink-0">
|
||||
<i class="pi pi-dollar text-xl text-blue-500"></i>
|
||||
</div>
|
||||
<span class="text-900 line-height-3"
|
||||
>Richard Jones
|
||||
<span class="text-700">has purchased a blue t-shirt for <span class="text-blue-500">79$</span></span>
|
||||
<span class="text-900 line-height-3">Richard Jones
|
||||
<span class="text-700">has purchased a blue t-shirt for <span
|
||||
class="text-blue-500">79$</span></span>
|
||||
</span>
|
||||
</li>
|
||||
<li class="flex align-items-center py-2">
|
||||
<div class="w-3rem h-3rem flex align-items-center justify-content-center bg-orange-100 border-circle mr-3 flex-shrink-0">
|
||||
<div
|
||||
class="w-3rem h-3rem flex align-items-center justify-content-center bg-orange-100 border-circle mr-3 flex-shrink-0">
|
||||
<i class="pi pi-download text-xl text-orange-500"></i>
|
||||
</div>
|
||||
<span class="text-700 line-height-3">Your request for withdrawal of <span class="text-blue-500 font-medium">2500$</span> has been initiated.</span>
|
||||
<span class="text-700 line-height-3">Your request for withdrawal of <span
|
||||
class="text-blue-500 font-medium">2500$</span> has been initiated.</span>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<span class="block text-600 font-medium mb-3">YESTERDAY</span>
|
||||
<ul class="p-0 m-0 list-none">
|
||||
<li class="flex align-items-center py-2 border-bottom-1 surface-border">
|
||||
<div class="w-3rem h-3rem flex align-items-center justify-content-center bg-blue-100 border-circle mr-3 flex-shrink-0">
|
||||
<div
|
||||
class="w-3rem h-3rem flex align-items-center justify-content-center bg-blue-100 border-circle mr-3 flex-shrink-0">
|
||||
<i class="pi pi-dollar text-xl text-blue-500"></i>
|
||||
</div>
|
||||
<span class="text-900 line-height-3"
|
||||
>Keyser Wick
|
||||
<span class="text-700">has purchased a black jacket for <span class="text-blue-500">59$</span></span>
|
||||
<span class="text-900 line-height-3">Keyser Wick
|
||||
<span class="text-700">has purchased a black jacket for <span
|
||||
class="text-blue-500">59$</span></span>
|
||||
</span>
|
||||
</li>
|
||||
<li class="flex align-items-center py-2 border-bottom-1 surface-border">
|
||||
<div class="w-3rem h-3rem flex align-items-center justify-content-center bg-pink-100 border-circle mr-3 flex-shrink-0">
|
||||
<div
|
||||
class="w-3rem h-3rem flex align-items-center justify-content-center bg-pink-100 border-circle mr-3 flex-shrink-0">
|
||||
<i class="pi pi-question text-xl text-pink-500"></i>
|
||||
</div>
|
||||
<span class="text-900 line-height-3"
|
||||
>Jane Davis
|
||||
<span class="text-900 line-height-3">Jane Davis
|
||||
<span class="text-700">has posted a new questions about your product.</span>
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div
|
||||
class="px-4 py-5 shadow-2 flex flex-column md:flex-row md:align-items-center justify-content-between mb-3"
|
||||
style="border-radius: 1rem; background: linear-gradient(0deg, rgba(0, 123, 255, 0.5), rgba(0, 123, 255, 0.5)), linear-gradient(92.54deg, #1c80cf 47.88%, #ffffff 100.01%)"
|
||||
>
|
||||
<div class="px-4 py-5 shadow-2 flex flex-column md:flex-row md:align-items-center justify-content-between mb-3"
|
||||
style="border-radius: 1rem; background: linear-gradient(0deg, rgba(0, 123, 255, 0.5), rgba(0, 123, 255, 0.5)), linear-gradient(92.54deg, #1c80cf 47.88%, #ffffff 100.01%)">
|
||||
<div>
|
||||
<div class="text-blue-100 font-medium text-xl mt-2 mb-3">TAKE THE NEXT STEP</div>
|
||||
<div class="text-white font-medium text-5xl">Try PrimeBlocks</div>
|
||||
</div>
|
||||
<div class="mt-4 mr-auto md:mt-0 md:mr-0">
|
||||
<a href="https://www.primefaces.org/primeblocks-vue" class="p-button font-bold px-5 py-3 p-button-warning p-button-rounded p-button-raised"> Get Started </a>
|
||||
<a href="https://www.primefaces.org/primeblocks-vue"
|
||||
class="p-button font-bold px-5 py-3 p-button-warning p-button-rounded p-button-raised"> Get
|
||||
Started </a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script setup>
|
||||
import { FilterMatchMode } from 'primevue/api';
|
||||
import { FilterMatchMode } from '@primevue/core/api';
|
||||
import { ref, onMounted, onBeforeMount } from 'vue';
|
||||
import { ProductService } from '@/service/ProductService';
|
||||
import { useToast } from 'primevue/usetoast';
|
||||
@@ -143,34 +143,30 @@ const initFilters = () => {
|
||||
<template v-slot:start>
|
||||
<div class="my-2">
|
||||
<Button label="New" icon="pi pi-plus" class="mr-2" severity="success" @click="openNew" />
|
||||
<Button label="Delete" icon="pi pi-trash" severity="danger" @click="confirmDeleteSelected" :disabled="!selectedProducts || !selectedProducts.length" />
|
||||
<Button label="Delete" icon="pi pi-trash" severity="danger" @click="confirmDeleteSelected"
|
||||
:disabled="!selectedProducts || !selectedProducts.length" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template v-slot:end>
|
||||
<FileUpload mode="basic" accept="image/*" :maxFileSize="1000000" label="Import" chooseLabel="Import" class="mr-2 inline-block" />
|
||||
<FileUpload mode="basic" accept="image/*" :maxFileSize="1000000" label="Import"
|
||||
chooseLabel="Import" class="mr-2 inline-block" />
|
||||
<Button label="Export" icon="pi pi-upload" severity="help" @click="exportCSV($event)" />
|
||||
</template>
|
||||
</Toolbar>
|
||||
|
||||
<DataTable
|
||||
ref="dt"
|
||||
:value="products"
|
||||
v-model:selection="selectedProducts"
|
||||
dataKey="id"
|
||||
:paginator="true"
|
||||
:rows="10"
|
||||
:filters="filters"
|
||||
<DataTable ref="dt" :value="products" v-model:selection="selectedProducts" dataKey="id"
|
||||
:paginator="true" :rows="10" :filters="filters"
|
||||
paginatorTemplate="FirstPageLink PrevPageLink PageLinks NextPageLink LastPageLink CurrentPageReport RowsPerPageDropdown"
|
||||
:rowsPerPageOptions="[5, 10, 25]"
|
||||
currentPageReportTemplate="Showing {first} to {last} of {totalRecords} products"
|
||||
>
|
||||
currentPageReportTemplate="Showing {first} to {last} of {totalRecords} products">
|
||||
<template #header>
|
||||
<div class="flex flex-column md:flex-row md:justify-content-between md:align-items-center">
|
||||
<h5 class="m-0">Manage Products</h5>
|
||||
<IconField iconPosition="left" class="block mt-2 md:mt-0">
|
||||
<InputIcon class="pi pi-search" />
|
||||
<InputText class="w-full sm:w-auto" v-model="filters['global'].value" placeholder="Search..." />
|
||||
<InputText class="w-full sm:w-auto" v-model="filters['global'].value"
|
||||
placeholder="Search..." />
|
||||
</IconField>
|
||||
</div>
|
||||
</template>
|
||||
@@ -191,7 +187,8 @@ const initFilters = () => {
|
||||
<Column header="Image" headerStyle="width:14%; min-width:10rem;">
|
||||
<template #body="slotProps">
|
||||
<span class="p-column-title">Image</span>
|
||||
<img :src="'/demo/images/product/' + slotProps.data.image" :alt="slotProps.data.image" class="shadow-2" width="100" />
|
||||
<img :src="'/demo/images/product/' + slotProps.data.image" :alt="slotProps.data.image"
|
||||
class="shadow-2" width="100" />
|
||||
</template>
|
||||
</Column>
|
||||
<Column field="price" header="Price" :sortable="true" headerStyle="width:14%; min-width:8rem;">
|
||||
@@ -200,7 +197,8 @@ const initFilters = () => {
|
||||
{{ formatCurrency(slotProps.data.price) }}
|
||||
</template>
|
||||
</Column>
|
||||
<Column field="category" header="Category" :sortable="true" headerStyle="width:14%; min-width:10rem;">
|
||||
<Column field="category" header="Category" :sortable="true"
|
||||
headerStyle="width:14%; min-width:10rem;">
|
||||
<template #body="slotProps">
|
||||
<span class="p-column-title">Category</span>
|
||||
{{ slotProps.data.category }}
|
||||
@@ -212,25 +210,32 @@ const initFilters = () => {
|
||||
<Rating :modelValue="slotProps.data.rating" :readonly="true" :cancel="false" />
|
||||
</template>
|
||||
</Column>
|
||||
<Column field="inventoryStatus" header="Status" :sortable="true" headerStyle="width:14%; min-width:10rem;">
|
||||
<Column field="inventoryStatus" header="Status" :sortable="true"
|
||||
headerStyle="width:14%; min-width:10rem;">
|
||||
<template #body="slotProps">
|
||||
<span class="p-column-title">Status</span>
|
||||
<Tag :severity="getBadgeSeverity(slotProps.data.inventoryStatus)">{{ slotProps.data.inventoryStatus }}</Tag>
|
||||
<Tag :severity="getBadgeSeverity(slotProps.data.inventoryStatus)">{{
|
||||
slotProps.data.inventoryStatus }}</Tag>
|
||||
</template>
|
||||
</Column>
|
||||
<Column headerStyle="min-width:10rem;">
|
||||
<template #body="slotProps">
|
||||
<Button icon="pi pi-pencil" class="mr-2" severity="success" rounded @click="editProduct(slotProps.data)" />
|
||||
<Button icon="pi pi-trash" class="mt-2" severity="warning" rounded @click="confirmDeleteProduct(slotProps.data)" />
|
||||
<Button icon="pi pi-pencil" class="mr-2" severity="success" rounded
|
||||
@click="editProduct(slotProps.data)" />
|
||||
<Button icon="pi pi-trash" class="mt-2" severity="warning" rounded
|
||||
@click="confirmDeleteProduct(slotProps.data)" />
|
||||
</template>
|
||||
</Column>
|
||||
</DataTable>
|
||||
|
||||
<Dialog v-model:visible="productDialog" :style="{ width: '450px' }" header="Product Details" :modal="true" class="p-fluid">
|
||||
<img :src="'/demo/images/product/' + product.image" :alt="product.image" v-if="product.image" width="150" class="mt-0 mx-auto mb-5 block shadow-2" />
|
||||
<Dialog v-model:visible="productDialog" :style="{ width: '450px' }" header="Product Details"
|
||||
:modal="true" class="p-fluid">
|
||||
<img :src="'/demo/images/product/' + product.image" :alt="product.image" v-if="product.image"
|
||||
width="150" class="mt-0 mx-auto mb-5 block shadow-2" />
|
||||
<div class="field">
|
||||
<label for="name">Name</label>
|
||||
<InputText id="name" v-model.trim="product.name" required="true" autofocus :invalid="submitted && !product.name" />
|
||||
<InputText id="name" v-model.trim="product.name" required="true" autofocus
|
||||
:invalid="submitted && !product.name" />
|
||||
<small class="p-invalid" v-if="submitted && !product.name">Name is required.</small>
|
||||
</div>
|
||||
<div class="field">
|
||||
@@ -240,13 +245,16 @@ const initFilters = () => {
|
||||
|
||||
<div class="field">
|
||||
<label for="inventoryStatus" class="mb-3">Inventory Status</label>
|
||||
<Dropdown id="inventoryStatus" v-model="product.inventoryStatus" :options="statuses" optionLabel="label" placeholder="Select a Status">
|
||||
<Dropdown id="inventoryStatus" v-model="product.inventoryStatus" :options="statuses"
|
||||
optionLabel="label" placeholder="Select a Status">
|
||||
<template #value="slotProps">
|
||||
<div v-if="slotProps.value && slotProps.value.value">
|
||||
<span :class="'product-badge status-' + slotProps.value.value">{{ slotProps.value.label }}</span>
|
||||
<span :class="'product-badge status-' + slotProps.value.value">{{
|
||||
slotProps.value.label }}</span>
|
||||
</div>
|
||||
<div v-else-if="slotProps.value && !slotProps.value.value">
|
||||
<span :class="'product-badge status-' + slotProps.value.toLowerCase()">{{ slotProps.value }}</span>
|
||||
<span :class="'product-badge status-' + slotProps.value.toLowerCase()">{{
|
||||
slotProps.value }}</span>
|
||||
</div>
|
||||
<span v-else>
|
||||
{{ slotProps.placeholder }}
|
||||
@@ -259,19 +267,23 @@ const initFilters = () => {
|
||||
<label class="mb-3">Category</label>
|
||||
<div class="formgrid grid">
|
||||
<div class="field-radiobutton col-6">
|
||||
<RadioButton id="category1" name="category" value="Accessories" v-model="product.category" />
|
||||
<RadioButton id="category1" name="category" value="Accessories"
|
||||
v-model="product.category" />
|
||||
<label for="category1">Accessories</label>
|
||||
</div>
|
||||
<div class="field-radiobutton col-6">
|
||||
<RadioButton id="category2" name="category" value="Clothing" v-model="product.category" />
|
||||
<RadioButton id="category2" name="category" value="Clothing"
|
||||
v-model="product.category" />
|
||||
<label for="category2">Clothing</label>
|
||||
</div>
|
||||
<div class="field-radiobutton col-6">
|
||||
<RadioButton id="category3" name="category" value="Electronics" v-model="product.category" />
|
||||
<RadioButton id="category3" name="category" value="Electronics"
|
||||
v-model="product.category" />
|
||||
<label for="category3">Electronics</label>
|
||||
</div>
|
||||
<div class="field-radiobutton col-6">
|
||||
<RadioButton id="category4" name="category" value="Fitness" v-model="product.category" />
|
||||
<RadioButton id="category4" name="category" value="Fitness"
|
||||
v-model="product.category" />
|
||||
<label for="category4">Fitness</label>
|
||||
</div>
|
||||
</div>
|
||||
@@ -280,7 +292,8 @@ const initFilters = () => {
|
||||
<div class="formgrid grid">
|
||||
<div class="field col">
|
||||
<label for="price">Price</label>
|
||||
<InputNumber id="price" v-model="product.price" mode="currency" currency="USD" locale="en-US" :invalid="submitted && !product.price" :required="true" />
|
||||
<InputNumber id="price" v-model="product.price" mode="currency" currency="USD"
|
||||
locale="en-US" :invalid="submitted && !product.price" :required="true" />
|
||||
<small class="p-invalid" v-if="submitted && !product.price">Price is required.</small>
|
||||
</div>
|
||||
<div class="field col">
|
||||
@@ -294,13 +307,11 @@ const initFilters = () => {
|
||||
</template>
|
||||
</Dialog>
|
||||
|
||||
<Dialog v-model:visible="deleteProductDialog" :style="{ width: '450px' }" header="Confirm" :modal="true">
|
||||
<Dialog v-model:visible="deleteProductDialog" :style="{ width: '450px' }" header="Confirm"
|
||||
:modal="true">
|
||||
<div class="flex align-items-center justify-content-center">
|
||||
<i class="pi pi-exclamation-triangle mr-3" style="font-size: 2rem" />
|
||||
<span v-if="product"
|
||||
>Are you sure you want to delete <b>{{ product.name }}</b
|
||||
>?</span
|
||||
>
|
||||
<span v-if="product">Are you sure you want to delete <b>{{ product.name }}</b>?</span>
|
||||
</div>
|
||||
<template #footer>
|
||||
<Button label="No" icon="pi pi-times" text @click="deleteProductDialog = false" />
|
||||
@@ -308,7 +319,8 @@ const initFilters = () => {
|
||||
</template>
|
||||
</Dialog>
|
||||
|
||||
<Dialog v-model:visible="deleteProductsDialog" :style="{ width: '450px' }" header="Confirm" :modal="true">
|
||||
<Dialog v-model:visible="deleteProductsDialog" :style="{ width: '450px' }" header="Confirm"
|
||||
:modal="true">
|
||||
<div class="flex align-items-center justify-content-center">
|
||||
<i class="pi pi-exclamation-triangle mr-3" style="font-size: 2rem" />
|
||||
<span v-if="product">Are you sure you want to delete the selected products?</span>
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<script setup>
|
||||
import { useLayout } from '@/layout/composables/layout';
|
||||
import { computed } from 'vue';
|
||||
import AppConfig from '@/layout/AppConfig.vue';
|
||||
|
||||
const { layoutConfig } = useLayout();
|
||||
|
||||
@@ -19,50 +18,63 @@ const logoUrl = computed(() => {
|
||||
<template>
|
||||
<div class="surface-0 flex justify-content-center">
|
||||
<div id="home" class="landing-wrapper overflow-hidden">
|
||||
<div class="py-4 px-4 mx-0 md:mx-6 lg:mx-8 lg:px-8 flex align-items-center justify-content-between relative lg:static mb-3">
|
||||
<a class="flex align-items-center" href="#"> <img :src="logoUrl" alt="Sakai Logo" height="50" class="mr-0 lg:mr-2" /><span class="text-900 font-medium text-2xl line-height-3 mr-8">SAKAI</span> </a>
|
||||
<a class="cursor-pointer block lg:hidden text-700 p-ripple" v-ripple v-styleclass="{ selector: '@next', enterClass: 'hidden', leaveToClass: 'hidden', hideOnOutsideClick: true }">
|
||||
<div
|
||||
class="py-4 px-4 mx-0 md:mx-6 lg:mx-8 lg:px-8 flex align-items-center justify-content-between relative lg:static mb-3">
|
||||
<a class="flex align-items-center" href="#"> <img :src="logoUrl" alt="Sakai Logo" height="50"
|
||||
class="mr-0 lg:mr-2" /><span
|
||||
class="text-900 font-medium text-2xl line-height-3 mr-8">SAKAI</span> </a>
|
||||
<a class="cursor-pointer block lg:hidden text-700 p-ripple" v-ripple
|
||||
v-styleclass="{ selector: '@next', enterClass: 'hidden', leaveToClass: 'hidden', hideOnOutsideClick: true }">
|
||||
<i class="pi pi-bars text-4xl"></i>
|
||||
</a>
|
||||
<div class="align-items-center surface-0 flex-grow-1 justify-content-between hidden lg:flex absolute lg:static w-full left-0 px-6 lg:px-0 z-2" style="top: 120px">
|
||||
<ul class="list-none p-0 m-0 flex lg:align-items-center select-none flex-column lg:flex-row cursor-pointer">
|
||||
<div class="align-items-center surface-0 flex-grow-1 justify-content-between hidden lg:flex absolute lg:static w-full left-0 px-6 lg:px-0 z-2"
|
||||
style="top: 120px">
|
||||
<ul
|
||||
class="list-none p-0 m-0 flex lg:align-items-center select-none flex-column lg:flex-row cursor-pointer">
|
||||
<li>
|
||||
<a @click="smoothScroll('#hero')" class="flex m-0 md:ml-5 px-0 py-3 text-900 font-medium line-height-3 p-ripple" v-ripple>
|
||||
<a @click="smoothScroll('#hero')"
|
||||
class="flex m-0 md:ml-5 px-0 py-3 text-900 font-medium line-height-3 p-ripple" v-ripple>
|
||||
<span>Home</span>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a @click="smoothScroll('#features')" class="flex m-0 md:ml-5 px-0 py-3 text-900 font-medium line-height-3 p-ripple" v-ripple>
|
||||
<a @click="smoothScroll('#features')"
|
||||
class="flex m-0 md:ml-5 px-0 py-3 text-900 font-medium line-height-3 p-ripple" v-ripple>
|
||||
<span>Features</span>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a @click="smoothScroll('#highlights')" class="flex m-0 md:ml-5 px-0 py-3 text-900 font-medium line-height-3 p-ripple" v-ripple>
|
||||
<a @click="smoothScroll('#highlights')"
|
||||
class="flex m-0 md:ml-5 px-0 py-3 text-900 font-medium line-height-3 p-ripple" v-ripple>
|
||||
<span>Highlights</span>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a @click="smoothScroll('#pricing')" class="flex m-0 md:ml-5 px-0 py-3 text-900 font-medium line-height-3 p-ripple" v-ripple>
|
||||
<a @click="smoothScroll('#pricing')"
|
||||
class="flex m-0 md:ml-5 px-0 py-3 text-900 font-medium line-height-3 p-ripple" v-ripple>
|
||||
<span>Pricing</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="flex justify-content-between lg:block border-top-1 lg:border-top-none surface-border py-3 lg:py-0 mt-3 lg:mt-0">
|
||||
<Button label="Login" class="p-button-text p-button-rounded border-none font-light line-height-2 text-blue-500"></Button>
|
||||
<Button label="Register" class="p-button-rounded border-none ml-5 font-light text-white line-height-2 bg-blue-500"></Button>
|
||||
<div
|
||||
class="flex justify-content-between lg:block border-top-1 lg:border-top-none surface-border py-3 lg:py-0 mt-3 lg:mt-0">
|
||||
<Button label="Login"
|
||||
class="p-button-text p-button-rounded border-none font-light line-height-2 text-blue-500"></Button>
|
||||
<Button label="Register"
|
||||
class="p-button-rounded border-none ml-5 font-light text-white line-height-2 bg-blue-500"></Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
id="hero"
|
||||
class="flex flex-column pt-4 px-4 lg:px-8 overflow-hidden"
|
||||
style="background: linear-gradient(0deg, rgba(255, 255, 255, 0.2), rgba(255, 255, 255, 0.2)), radial-gradient(77.36% 256.97% at 77.36% 57.52%, rgb(238, 239, 175) 0%, rgb(195, 227, 250) 100%); clip-path: ellipse(150% 87% at 93% 13%)"
|
||||
>
|
||||
<div id="hero" class="flex flex-column pt-4 px-4 lg:px-8 overflow-hidden"
|
||||
style="background: linear-gradient(0deg, rgba(255, 255, 255, 0.2), rgba(255, 255, 255, 0.2)), radial-gradient(77.36% 256.97% at 77.36% 57.52%, rgb(238, 239, 175) 0%, rgb(195, 227, 250) 100%); clip-path: ellipse(150% 87% at 93% 13%)">
|
||||
<div class="mx-4 md:mx-8 mt-0 md:mt-4">
|
||||
<h1 class="text-6xl font-bold text-gray-900 line-height-2"><span class="font-light block">Eu sem integer</span>eget magna fermentum</h1>
|
||||
<p class="font-normal text-2xl line-height-3 md:mt-3 text-gray-700">Sed blandit libero volutpat sed cras. Fames ac turpis egestas integer. Placerat in egestas erat...</p>
|
||||
<Button label="Get Started" class="p-button-rounded text-xl border-none mt-5 bg-blue-500 font-normal text-white line-height-3 px-3"></Button>
|
||||
<h1 class="text-6xl font-bold text-gray-900 line-height-2"><span class="font-light block">Eu sem
|
||||
integer</span>eget magna fermentum</h1>
|
||||
<p class="font-normal text-2xl line-height-3 md:mt-3 text-gray-700">Sed blandit libero volutpat sed
|
||||
cras. Fames ac turpis egestas integer. Placerat in egestas erat...</p>
|
||||
<Button label="Get Started"
|
||||
class="p-button-rounded text-xl border-none mt-5 bg-blue-500 font-normal text-white line-height-3 px-3"></Button>
|
||||
</div>
|
||||
<div class="flex justify-content-center md:justify-content-end">
|
||||
<img src="/demo/images/landing/screen-1.png" alt="Hero Image" class="w-9 md:w-auto" />
|
||||
@@ -78,10 +90,10 @@ const logoUrl = computed(() => {
|
||||
|
||||
<div class="col-12 md:col-12 lg:col-4 p-0 lg:pr-5 lg:pb-5 mt-4 lg:mt-0">
|
||||
<div
|
||||
style="height: 160px; padding: 2px; border-radius: 10px; background: linear-gradient(90deg, rgba(253, 228, 165, 0.2), rgba(187, 199, 205, 0.2)), linear-gradient(180deg, rgba(253, 228, 165, 0.2), rgba(187, 199, 205, 0.2))"
|
||||
>
|
||||
style="height: 160px; padding: 2px; border-radius: 10px; background: linear-gradient(90deg, rgba(253, 228, 165, 0.2), rgba(187, 199, 205, 0.2)), linear-gradient(180deg, rgba(253, 228, 165, 0.2), rgba(187, 199, 205, 0.2))">
|
||||
<div class="p-3 surface-card h-full" style="border-radius: 8px">
|
||||
<div class="flex align-items-center justify-content-center bg-yellow-200 mb-3" style="width: 3.5rem; height: 3.5rem; border-radius: 10px">
|
||||
<div class="flex align-items-center justify-content-center bg-yellow-200 mb-3"
|
||||
style="width: 3.5rem; height: 3.5rem; border-radius: 10px">
|
||||
<i class="pi pi-fw pi-users text-2xl text-yellow-700"></i>
|
||||
</div>
|
||||
<h5 class="mb-2 text-900">Easy to Use</h5>
|
||||
@@ -92,10 +104,10 @@ const logoUrl = computed(() => {
|
||||
|
||||
<div class="col-12 md:col-12 lg:col-4 p-0 lg:pr-5 lg:pb-5 mt-4 lg:mt-0">
|
||||
<div
|
||||
style="height: 160px; padding: 2px; border-radius: 10px; background: linear-gradient(90deg, rgba(145, 226, 237, 0.2), rgba(251, 199, 145, 0.2)), linear-gradient(180deg, rgba(253, 228, 165, 0.2), rgba(172, 180, 223, 0.2))"
|
||||
>
|
||||
style="height: 160px; padding: 2px; border-radius: 10px; background: linear-gradient(90deg, rgba(145, 226, 237, 0.2), rgba(251, 199, 145, 0.2)), linear-gradient(180deg, rgba(253, 228, 165, 0.2), rgba(172, 180, 223, 0.2))">
|
||||
<div class="p-3 surface-card h-full" style="border-radius: 8px">
|
||||
<div class="flex align-items-center justify-content-center bg-cyan-200 mb-3" style="width: 3.5rem; height: 3.5rem; border-radius: 10px">
|
||||
<div class="flex align-items-center justify-content-center bg-cyan-200 mb-3"
|
||||
style="width: 3.5rem; height: 3.5rem; border-radius: 10px">
|
||||
<i class="pi pi-fw pi-palette text-2xl text-cyan-700"></i>
|
||||
</div>
|
||||
<h5 class="mb-2 text-900">Fresh Design</h5>
|
||||
@@ -106,10 +118,10 @@ const logoUrl = computed(() => {
|
||||
|
||||
<div class="col-12 md:col-12 lg:col-4 p-0 lg:pb-5 mt-4 lg:mt-0">
|
||||
<div
|
||||
style="height: 160px; padding: 2px; border-radius: 10px; background: linear-gradient(90deg, rgba(145, 226, 237, 0.2), rgba(172, 180, 223, 0.2)), linear-gradient(180deg, rgba(172, 180, 223, 0.2), rgba(246, 158, 188, 0.2))"
|
||||
>
|
||||
style="height: 160px; padding: 2px; border-radius: 10px; background: linear-gradient(90deg, rgba(145, 226, 237, 0.2), rgba(172, 180, 223, 0.2)), linear-gradient(180deg, rgba(172, 180, 223, 0.2), rgba(246, 158, 188, 0.2))">
|
||||
<div class="p-3 surface-card h-full" style="border-radius: 8px">
|
||||
<div class="flex align-items-center justify-content-center bg-indigo-200" style="width: 3.5rem; height: 3.5rem; border-radius: 10px">
|
||||
<div class="flex align-items-center justify-content-center bg-indigo-200"
|
||||
style="width: 3.5rem; height: 3.5rem; border-radius: 10px">
|
||||
<i class="pi pi-fw pi-map text-2xl text-indigo-700"></i>
|
||||
</div>
|
||||
<h5 class="mb-2 text-900">Well Documented</h5>
|
||||
@@ -120,10 +132,10 @@ const logoUrl = computed(() => {
|
||||
|
||||
<div class="col-12 md:col-12 lg:col-4 p-0 lg:pr-5 lg:pb-5 mt-4 lg:mt-0">
|
||||
<div
|
||||
style="height: 160px; padding: 2px; border-radius: 10px; background: linear-gradient(90deg, rgba(187, 199, 205, 0.2), rgba(251, 199, 145, 0.2)), linear-gradient(180deg, rgba(253, 228, 165, 0.2), rgba(145, 210, 204, 0.2))"
|
||||
>
|
||||
style="height: 160px; padding: 2px; border-radius: 10px; background: linear-gradient(90deg, rgba(187, 199, 205, 0.2), rgba(251, 199, 145, 0.2)), linear-gradient(180deg, rgba(253, 228, 165, 0.2), rgba(145, 210, 204, 0.2))">
|
||||
<div class="p-3 surface-card h-full" style="border-radius: 8px">
|
||||
<div class="flex align-items-center justify-content-center bg-bluegray-200 mb-3" style="width: 3.5rem; height: 3.5rem; border-radius: 10px">
|
||||
<div class="flex align-items-center justify-content-center bg-bluegray-200 mb-3"
|
||||
style="width: 3.5rem; height: 3.5rem; border-radius: 10px">
|
||||
<i class="pi pi-fw pi-id-card text-2xl text-bluegray-700"></i>
|
||||
</div>
|
||||
<h5 class="mb-2 text-900">Responsive Layout</h5>
|
||||
@@ -134,10 +146,10 @@ const logoUrl = computed(() => {
|
||||
|
||||
<div class="col-12 md:col-12 lg:col-4 p-0 lg:pr-5 lg:pb-5 mt-4 lg:mt-0">
|
||||
<div
|
||||
style="height: 160px; padding: 2px; border-radius: 10px; background: linear-gradient(90deg, rgba(187, 199, 205, 0.2), rgba(246, 158, 188, 0.2)), linear-gradient(180deg, rgba(145, 226, 237, 0.2), rgba(160, 210, 250, 0.2))"
|
||||
>
|
||||
style="height: 160px; padding: 2px; border-radius: 10px; background: linear-gradient(90deg, rgba(187, 199, 205, 0.2), rgba(246, 158, 188, 0.2)), linear-gradient(180deg, rgba(145, 226, 237, 0.2), rgba(160, 210, 250, 0.2))">
|
||||
<div class="p-3 surface-card h-full" style="border-radius: 8px">
|
||||
<div class="flex align-items-center justify-content-center bg-orange-200 mb-3" style="width: 3.5rem; height: 3.5rem; border-radius: 10px">
|
||||
<div class="flex align-items-center justify-content-center bg-orange-200 mb-3"
|
||||
style="width: 3.5rem; height: 3.5rem; border-radius: 10px">
|
||||
<i class="pi pi-fw pi-star text-2xl text-orange-700"></i>
|
||||
</div>
|
||||
<h5 class="mb-2 text-900">Clean Code</h5>
|
||||
@@ -148,10 +160,10 @@ const logoUrl = computed(() => {
|
||||
|
||||
<div class="col-12 md:col-12 lg:col-4 p-0 lg:pb-5 mt-4 lg:mt-0">
|
||||
<div
|
||||
style="height: 160px; padding: 2px; border-radius: 10px; background: linear-gradient(90deg, rgba(251, 199, 145, 0.2), rgba(246, 158, 188, 0.2)), linear-gradient(180deg, rgba(172, 180, 223, 0.2), rgba(212, 162, 221, 0.2))"
|
||||
>
|
||||
style="height: 160px; padding: 2px; border-radius: 10px; background: linear-gradient(90deg, rgba(251, 199, 145, 0.2), rgba(246, 158, 188, 0.2)), linear-gradient(180deg, rgba(172, 180, 223, 0.2), rgba(212, 162, 221, 0.2))">
|
||||
<div class="p-3 surface-card h-full" style="border-radius: 8px">
|
||||
<div class="flex align-items-center justify-content-center bg-pink-200 mb-3" style="width: 3.5rem; height: 3.5rem; border-radius: 10px">
|
||||
<div class="flex align-items-center justify-content-center bg-pink-200 mb-3"
|
||||
style="width: 3.5rem; height: 3.5rem; border-radius: 10px">
|
||||
<i class="pi pi-fw pi-moon text-2xl text-pink-700"></i>
|
||||
</div>
|
||||
<h5 class="mb-2 text-900">Dark Mode</h5>
|
||||
@@ -162,10 +174,10 @@ const logoUrl = computed(() => {
|
||||
|
||||
<div class="col-12 md:col-12 lg:col-4 p-0 lg:pr-5 mt-4 lg:mt-0">
|
||||
<div
|
||||
style="height: 160px; padding: 2px; border-radius: 10px; background: linear-gradient(90deg, rgba(145, 210, 204, 0.2), rgba(160, 210, 250, 0.2)), linear-gradient(180deg, rgba(187, 199, 205, 0.2), rgba(145, 210, 204, 0.2))"
|
||||
>
|
||||
style="height: 160px; padding: 2px; border-radius: 10px; background: linear-gradient(90deg, rgba(145, 210, 204, 0.2), rgba(160, 210, 250, 0.2)), linear-gradient(180deg, rgba(187, 199, 205, 0.2), rgba(145, 210, 204, 0.2))">
|
||||
<div class="p-3 surface-card h-full" style="border-radius: 8px">
|
||||
<div class="flex align-items-center justify-content-center bg-teal-200 mb-3" style="width: 3.5rem; height: 3.5rem; border-radius: 10px">
|
||||
<div class="flex align-items-center justify-content-center bg-teal-200 mb-3"
|
||||
style="width: 3.5rem; height: 3.5rem; border-radius: 10px">
|
||||
<i class="pi pi-fw pi-shopping-cart text-2xl text-teal-700"></i>
|
||||
</div>
|
||||
<h5 class="mb-2 text-900">Ready to Use</h5>
|
||||
@@ -176,10 +188,10 @@ const logoUrl = computed(() => {
|
||||
|
||||
<div class="col-12 md:col-12 lg:col-4 p-0 lg:pr-5 mt-4 lg:mt-0">
|
||||
<div
|
||||
style="height: 160px; padding: 2px; border-radius: 10px; background: linear-gradient(90deg, rgba(145, 210, 204, 0.2), rgba(212, 162, 221, 0.2)), linear-gradient(180deg, rgba(251, 199, 145, 0.2), rgba(160, 210, 250, 0.2))"
|
||||
>
|
||||
style="height: 160px; padding: 2px; border-radius: 10px; background: linear-gradient(90deg, rgba(145, 210, 204, 0.2), rgba(212, 162, 221, 0.2)), linear-gradient(180deg, rgba(251, 199, 145, 0.2), rgba(160, 210, 250, 0.2))">
|
||||
<div class="p-3 surface-card h-full" style="border-radius: 8px">
|
||||
<div class="flex align-items-center justify-content-center bg-blue-200 mb-3" style="width: 3.5rem; height: 3.5rem; border-radius: 10px">
|
||||
<div class="flex align-items-center justify-content-center bg-blue-200 mb-3"
|
||||
style="width: 3.5rem; height: 3.5rem; border-radius: 10px">
|
||||
<i class="pi pi-fw pi-globe text-2xl text-blue-700"></i>
|
||||
</div>
|
||||
<h5 class="mb-2 text-900">Modern Practices</h5>
|
||||
@@ -190,10 +202,10 @@ const logoUrl = computed(() => {
|
||||
|
||||
<div class="col-12 md:col-12 lg:col-4 p-0 lg-4 mt-4 lg:mt-0">
|
||||
<div
|
||||
style="height: 160px; padding: 2px; border-radius: 10px; background: linear-gradient(90deg, rgba(160, 210, 250, 0.2), rgba(212, 162, 221, 0.2)), linear-gradient(180deg, rgba(246, 158, 188, 0.2), rgba(212, 162, 221, 0.2))"
|
||||
>
|
||||
style="height: 160px; padding: 2px; border-radius: 10px; background: linear-gradient(90deg, rgba(160, 210, 250, 0.2), rgba(212, 162, 221, 0.2)), linear-gradient(180deg, rgba(246, 158, 188, 0.2), rgba(212, 162, 221, 0.2))">
|
||||
<div class="p-3 surface-card h-full" style="border-radius: 8px">
|
||||
<div class="flex align-items-center justify-content-center bg-purple-200 mb-3" style="width: 3.5rem; height: 3.5rem; border-radius: 10px">
|
||||
<div class="flex align-items-center justify-content-center bg-purple-200 mb-3"
|
||||
style="width: 3.5rem; height: 3.5rem; border-radius: 10px">
|
||||
<i class="pi pi-fw pi-eye text-2xl text-purple-700"></i>
|
||||
</div>
|
||||
<h5 class="mb-2 text-900">Privacy</h5>
|
||||
@@ -202,15 +214,17 @@ const logoUrl = computed(() => {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="col-12 mt-8 mb-8 p-2 md:p-8"
|
||||
style="border-radius: 20px; background: linear-gradient(0deg, rgba(255, 255, 255, 0.6), rgba(255, 255, 255, 0.6)), radial-gradient(77.36% 256.97% at 77.36% 57.52%, #efe1af 0%, #c3dcfa 100%)"
|
||||
>
|
||||
<div class="flex flex-column justify-content-center align-items-center text-center px-3 py-3 md:py-0">
|
||||
<div class="col-12 mt-8 mb-8 p-2 md:p-8"
|
||||
style="border-radius: 20px; background: linear-gradient(0deg, rgba(255, 255, 255, 0.6), rgba(255, 255, 255, 0.6)), radial-gradient(77.36% 256.97% at 77.36% 57.52%, #efe1af 0%, #c3dcfa 100%)">
|
||||
<div
|
||||
class="flex flex-column justify-content-center align-items-center text-center px-3 py-3 md:py-0">
|
||||
<h3 class="text-gray-900 mb-2">Joséphine Miller</h3>
|
||||
<span class="text-gray-600 text-2xl">Peak Interactive</span>
|
||||
<p class="text-gray-900 sm:line-height-2 md:line-height-4 text-2xl mt-4" style="max-width: 800px">
|
||||
“Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.”
|
||||
<p class="text-gray-900 sm:line-height-2 md:line-height-4 text-2xl mt-4"
|
||||
style="max-width: 800px">
|
||||
“Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat
|
||||
nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui
|
||||
officia deserunt mollit anim id est laborum.”
|
||||
</p>
|
||||
<img src="/demo/images/landing/peak-logo.svg" class="mt-4" alt="Company logo" />
|
||||
</div>
|
||||
@@ -225,33 +239,38 @@ const logoUrl = computed(() => {
|
||||
</div>
|
||||
|
||||
<div class="grid mt-8 pb-2 md:pb-8">
|
||||
<div class="flex justify-content-center col-12 lg:col-6 bg-purple-100 p-0 flex-order-1 lg:flex-order-0" style="border-radius: 8px">
|
||||
<div class="flex justify-content-center col-12 lg:col-6 bg-purple-100 p-0 flex-order-1 lg:flex-order-0"
|
||||
style="border-radius: 8px">
|
||||
<img src="/demo/images/landing/mockup.svg" class="w-11" alt="mockup mobile" />
|
||||
</div>
|
||||
|
||||
<div class="col-12 lg:col-6 my-auto flex flex-column lg:align-items-end text-center lg:text-right">
|
||||
<div class="flex align-items-center justify-content-center bg-purple-200 align-self-center lg:align-self-end" style="width: 4.2rem; height: 4.2rem; border-radius: 10px">
|
||||
<div class="flex align-items-center justify-content-center bg-purple-200 align-self-center lg:align-self-end"
|
||||
style="width: 4.2rem; height: 4.2rem; border-radius: 10px">
|
||||
<i class="pi pi-fw pi-mobile text-5xl text-purple-700"></i>
|
||||
</div>
|
||||
<h2 class="line-height-1 text-900 text-4xl font-normal">Congue Quisque Egestas</h2>
|
||||
<span class="text-700 text-2xl line-height-3 ml-0 md:ml-2" style="max-width: 650px"
|
||||
>Lectus arcu bibendum at varius vel pharetra vel turpis nunc. Eget aliquet nibh praesent tristique magna sit amet purus gravida. Sit amet mattis vulputate enim nulla aliquet.</span
|
||||
>
|
||||
<span class="text-700 text-2xl line-height-3 ml-0 md:ml-2" style="max-width: 650px">Lectus arcu
|
||||
bibendum at varius vel pharetra vel turpis nunc. Eget aliquet nibh praesent tristique magna
|
||||
sit amet purus gravida. Sit amet mattis vulputate enim nulla aliquet.</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="grid my-8 pt-2 md:pt-8">
|
||||
<div class="col-12 lg:col-6 my-auto flex flex-column text-center lg:text-left lg:align-items-start">
|
||||
<div class="flex align-items-center justify-content-center bg-yellow-200 align-self-center lg:align-self-start" style="width: 4.2rem; height: 4.2rem; border-radius: 10px">
|
||||
<div class="flex align-items-center justify-content-center bg-yellow-200 align-self-center lg:align-self-start"
|
||||
style="width: 4.2rem; height: 4.2rem; border-radius: 10px">
|
||||
<i class="pi pi-fw pi-desktop text-5xl text-yellow-700"></i>
|
||||
</div>
|
||||
<h2 class="line-height-1 text-900 text-4xl font-normal">Celerisque Eu Ultrices</h2>
|
||||
<span class="text-700 text-2xl line-height-3 mr-0 md:mr-2" style="max-width: 650px"
|
||||
>Adipiscing commodo elit at imperdiet dui. Viverra nibh cras pulvinar mattis nunc sed blandit libero. Suspendisse in est ante in. Mauris pharetra et ultrices neque ornare aenean euismod elementum nisi.</span
|
||||
>
|
||||
<span class="text-700 text-2xl line-height-3 mr-0 md:mr-2" style="max-width: 650px">Adipiscing
|
||||
commodo elit at imperdiet dui. Viverra nibh cras pulvinar mattis nunc sed blandit libero.
|
||||
Suspendisse in est ante in. Mauris pharetra et ultrices neque ornare aenean euismod
|
||||
elementum nisi.</span>
|
||||
</div>
|
||||
|
||||
<div class="flex justify-content-end flex-order-1 sm:flex-order-2 col-12 lg:col-6 bg-yellow-100 p-0" style="border-radius: 8px">
|
||||
<div class="flex justify-content-end flex-order-1 sm:flex-order-2 col-12 lg:col-6 bg-yellow-100 p-0"
|
||||
style="border-radius: 8px">
|
||||
<img src="/demo/images/landing/mockup-desktop.svg" class="w-11" alt="mockup" />
|
||||
</div>
|
||||
</div>
|
||||
@@ -265,13 +284,15 @@ const logoUrl = computed(() => {
|
||||
|
||||
<div class="grid justify-content-between mt-8 md:mt-0">
|
||||
<div class="col-12 lg:col-4 p-0 md:p-3">
|
||||
<div class="p-3 flex flex-column border-200 pricing-card cursor-pointer border-2 hover:border-primary transition-duration-300 transition-all" style="border-radius: 10px">
|
||||
<div class="p-3 flex flex-column border-200 pricing-card cursor-pointer border-2 hover:border-primary transition-duration-300 transition-all"
|
||||
style="border-radius: 10px">
|
||||
<h3 class="text-900 text-center my-5">Free</h3>
|
||||
<img src="/demo/images/landing/free.svg" class="w-10 h-10 mx-auto" alt="free" />
|
||||
<div class="my-5 text-center">
|
||||
<span class="text-5xl font-bold mr-2 text-900">$0</span>
|
||||
<span class="text-600">per month</span>
|
||||
<Button label="Get Started" class="block mx-auto mt-4 p-button-rounded border-none ml-3 font-light line-height-2 bg-blue-500 text-white"></Button>
|
||||
<Button label="Get Started"
|
||||
class="block mx-auto mt-4 p-button-rounded border-none ml-3 font-light line-height-2 bg-blue-500 text-white"></Button>
|
||||
</div>
|
||||
<Divider class="w-full bg-surface-200"></Divider>
|
||||
<ul class="my-5 list-none p-0 flex text-900 flex-column">
|
||||
@@ -296,13 +317,15 @@ const logoUrl = computed(() => {
|
||||
</div>
|
||||
|
||||
<div class="col-12 lg:col-4 p-0 md:p-3 mt-4 md:mt-0">
|
||||
<div class="p-3 flex flex-column border-200 pricing-card cursor-pointer border-2 hover:border-primary transition-duration-300 transition-all" style="border-radius: 10px">
|
||||
<div class="p-3 flex flex-column border-200 pricing-card cursor-pointer border-2 hover:border-primary transition-duration-300 transition-all"
|
||||
style="border-radius: 10px">
|
||||
<h3 class="text-900 text-center my-5">Startup</h3>
|
||||
<img src="/demo/images/landing/startup.svg" class="w-10 h-10 mx-auto" alt="startup" />
|
||||
<div class="my-5 text-center">
|
||||
<span class="text-5xl font-bold mr-2 text-900">$1</span>
|
||||
<span class="text-600">per month</span>
|
||||
<Button label="Try Free" class="block mx-auto mt-4 p-button-rounded border-none ml-3 font-light line-height-2 bg-blue-500 text-white"></Button>
|
||||
<Button label="Try Free"
|
||||
class="block mx-auto mt-4 p-button-rounded border-none ml-3 font-light line-height-2 bg-blue-500 text-white"></Button>
|
||||
</div>
|
||||
<Divider class="w-full bg-surface-200"></Divider>
|
||||
<ul class="my-5 list-none p-0 flex text-900 flex-column">
|
||||
@@ -327,13 +350,15 @@ const logoUrl = computed(() => {
|
||||
</div>
|
||||
|
||||
<div class="col-12 lg:col-4 p-0 md:p-3 mt-4 md:mt-0">
|
||||
<div class="p-3 flex flex-column border-200 pricing-card cursor-pointer border-2 hover:border-primary transition-duration-300 transition-all" style="border-radius: 10px">
|
||||
<div class="p-3 flex flex-column border-200 pricing-card cursor-pointer border-2 hover:border-primary transition-duration-300 transition-all"
|
||||
style="border-radius: 10px">
|
||||
<h3 class="text-900 text-center my-5">Enterprise</h3>
|
||||
<img src="/demo/images/landing/enterprise.svg" class="w-10 h-10 mx-auto" alt="enterprise" />
|
||||
<div class="my-5 text-center">
|
||||
<span class="text-5xl font-bold mr-2 text-900">$999</span>
|
||||
<span class="text-600">per month</span>
|
||||
<Button label="Get a Quote" class="block mx-auto mt-4 p-button-rounded border-none ml-3 font-light line-height-2 bg-blue-500 text-white"></Button>
|
||||
<Button label="Get a Quote"
|
||||
class="block mx-auto mt-4 p-button-rounded border-none ml-3 font-light line-height-2 bg-blue-500 text-white"></Button>
|
||||
</div>
|
||||
<Divider class="w-full bg-surface-200"></Divider>
|
||||
<ul class="my-5 list-none p-0 flex text-900 flex-column">
|
||||
@@ -362,7 +387,8 @@ const logoUrl = computed(() => {
|
||||
<div class="py-4 px-4 mx-0 mt-8 lg:mx-8">
|
||||
<div class="grid justify-content-between">
|
||||
<div class="col-12 md:col-2" style="margin-top: -1.5rem">
|
||||
<a @click="smoothScroll('#home')" class="flex flex-wrap align-items-center justify-content-center md:justify-content-start md:mb-0 mb-3 cursor-pointer">
|
||||
<a @click="smoothScroll('#home')"
|
||||
class="flex flex-wrap align-items-center justify-content-center md:justify-content-start md:mb-0 mb-3 cursor-pointer">
|
||||
<img :src="logoUrl" alt="footer sections" width="50" height="50" class="mr-2" />
|
||||
<h4 class="font-medium text-3xl text-900">SAKAI</h4>
|
||||
</a>
|
||||
@@ -374,7 +400,8 @@ const logoUrl = computed(() => {
|
||||
<h4 class="font-medium text-2xl line-height-3 mb-3 text-900">Company</h4>
|
||||
<a class="line-height-3 text-xl block cursor-pointer mb-2 text-700">About Us</a>
|
||||
<a class="line-height-3 text-xl block cursor-pointer mb-2 text-700">News</a>
|
||||
<a class="line-height-3 text-xl block cursor-pointer mb-2 text-700">Investor Relations</a>
|
||||
<a class="line-height-3 text-xl block cursor-pointer mb-2 text-700">Investor
|
||||
Relations</a>
|
||||
<a class="line-height-3 text-xl block cursor-pointer mb-2 text-700">Careers</a>
|
||||
<a class="line-height-3 text-xl block cursor-pointer text-700">Media Kit</a>
|
||||
</div>
|
||||
@@ -389,7 +416,8 @@ const logoUrl = computed(() => {
|
||||
<div class="col-12 md:col-3 mt-4 md:mt-0">
|
||||
<h4 class="font-medium text-2xl line-height-3 mb-3 text-900">Community</h4>
|
||||
<a class="line-height-3 text-xl block cursor-pointer mb-2 text-700">Discord</a>
|
||||
<a class="line-height-3 text-xl block cursor-pointer mb-2 text-700">Events<img src="/demo/images/landing/new-badge.svg" class="ml-2" /></a>
|
||||
<a class="line-height-3 text-xl block cursor-pointer mb-2 text-700">Events<img
|
||||
src="/demo/images/landing/new-badge.svg" class="ml-2" /></a>
|
||||
<a class="line-height-3 text-xl block cursor-pointer mb-2 text-700">FAQ</a>
|
||||
<a class="line-height-3 text-xl block cursor-pointer text-700">Blog</a>
|
||||
</div>
|
||||
@@ -406,7 +434,6 @@ const logoUrl = computed(() => {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<AppConfig simple />
|
||||
</template>
|
||||
|
||||
<!-- <style scoped>
|
||||
|
||||
@@ -1,18 +1,20 @@
|
||||
<script setup>
|
||||
import AppConfig from '@/layout/AppConfig.vue';
|
||||
</script>
|
||||
<script setup></script>
|
||||
|
||||
<template>
|
||||
<div class="surface-ground flex align-items-center justify-content-center min-h-screen min-w-screen overflow-hidden">
|
||||
<div
|
||||
class="surface-ground flex align-items-center justify-content-center min-h-screen min-w-screen overflow-hidden">
|
||||
<div class="flex flex-column align-items-center justify-content-center">
|
||||
<img src="/demo/images/notfound/logo-blue.svg" alt="Sakai logo" class="mb-5 w-6rem flex-shrink-0" />
|
||||
<div style="border-radius: 56px; padding: 0.3rem; background: linear-gradient(180deg, rgba(33, 150, 243, 0.4) 10%, rgba(33, 150, 243, 0) 30%)">
|
||||
<div class="w-full surface-card py-8 px-5 sm:px-8 flex flex-column align-items-center" style="border-radius: 53px">
|
||||
<div
|
||||
style="border-radius: 56px; padding: 0.3rem; background: linear-gradient(180deg, rgba(33, 150, 243, 0.4) 10%, rgba(33, 150, 243, 0) 30%)">
|
||||
<div class="w-full surface-card py-8 px-5 sm:px-8 flex flex-column align-items-center"
|
||||
style="border-radius: 53px">
|
||||
<span class="text-blue-500 font-bold text-3xl">404</span>
|
||||
<h1 class="text-900 font-bold text-3xl lg:text-5xl mb-2">Not Found</h1>
|
||||
<div class="text-600 mb-5">Requested resource is not available.</div>
|
||||
<router-link to="/" class="w-full flex align-items-center py-5 border-300 border-bottom-1">
|
||||
<span class="flex justify-content-center align-items-center bg-cyan-400 border-round" style="height: 3.5rem; width: 3.5rem">
|
||||
<span class="flex justify-content-center align-items-center bg-cyan-400 border-round"
|
||||
style="height: 3.5rem; width: 3.5rem">
|
||||
<i class="text-50 pi pi-fw pi-table text-2xl"></i>
|
||||
</span>
|
||||
<span class="ml-4 flex flex-column">
|
||||
@@ -21,7 +23,8 @@ import AppConfig from '@/layout/AppConfig.vue';
|
||||
</span>
|
||||
</router-link>
|
||||
<router-link to="/" class="w-full flex align-items-center py-5 border-300 border-bottom-1">
|
||||
<span class="flex justify-content-center align-items-center bg-orange-400 border-round" style="height: 3.5rem; width: 3.5rem">
|
||||
<span class="flex justify-content-center align-items-center bg-orange-400 border-round"
|
||||
style="height: 3.5rem; width: 3.5rem">
|
||||
<i class="pi pi-fw pi-question-circle text-50 text-2xl"></i>
|
||||
</span>
|
||||
<span class="ml-4 flex flex-column">
|
||||
@@ -30,7 +33,8 @@ import AppConfig from '@/layout/AppConfig.vue';
|
||||
</span>
|
||||
</router-link>
|
||||
<router-link to="/" class="w-full flex align-items-center mb-5 py-5 border-300 border-bottom-1">
|
||||
<span class="flex justify-content-center align-items-center bg-indigo-400 border-round" style="height: 3.5rem; width: 3.5rem">
|
||||
<span class="flex justify-content-center align-items-center bg-indigo-400 border-round"
|
||||
style="height: 3.5rem; width: 3.5rem">
|
||||
<i class="pi pi-fw pi-unlock text-50 text-2xl"></i>
|
||||
</span>
|
||||
<span class="ml-4 flex flex-column">
|
||||
@@ -42,5 +46,4 @@ import AppConfig from '@/layout/AppConfig.vue';
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<AppConfig simple />
|
||||
</template>
|
||||
|
||||
@@ -1,19 +1,22 @@
|
||||
<script setup>
|
||||
import AppConfig from '@/layout/AppConfig.vue';
|
||||
</script>
|
||||
<script setup></script>
|
||||
|
||||
<template>
|
||||
<div class="surface-ground flex align-items-center justify-content-center min-h-screen min-w-screen overflow-hidden">
|
||||
<div
|
||||
class="surface-ground flex align-items-center justify-content-center min-h-screen min-w-screen overflow-hidden">
|
||||
<div class="flex flex-column align-items-center justify-content-center">
|
||||
<img src="/demo/images/access/logo-orange.svg" alt="Sakai logo" class="mb-5 w-6rem flex-shrink-0" />
|
||||
<div style="border-radius: 56px; padding: 0.3rem; background: linear-gradient(180deg, rgba(247, 149, 48, 0.4) 10%, rgba(247, 149, 48, 0) 30%)">
|
||||
<div class="w-full surface-card py-8 px-5 sm:px-8 flex flex-column align-items-center" style="border-radius: 53px">
|
||||
<div
|
||||
style="border-radius: 56px; padding: 0.3rem; background: linear-gradient(180deg, rgba(247, 149, 48, 0.4) 10%, rgba(247, 149, 48, 0) 30%)">
|
||||
<div class="w-full surface-card py-8 px-5 sm:px-8 flex flex-column align-items-center"
|
||||
style="border-radius: 53px">
|
||||
<div class="grid flex flex-column align-items-center">
|
||||
<div class="flex justify-content-center align-items-center bg-orange-500 border-circle" style="width: 3.2rem; height: 3.2rem">
|
||||
<div class="flex justify-content-center align-items-center bg-orange-500 border-circle"
|
||||
style="width: 3.2rem; height: 3.2rem">
|
||||
<i class="text-50 pi pi-fw pi-lock text-2xl"></i>
|
||||
</div>
|
||||
<h1 class="text-900 font-bold text-4xl lg:text-5xl mb-2">Access Denied</h1>
|
||||
<span class="text-600 mb-5">You do not have the necessary permisions. Please contact admins.</span>
|
||||
<span class="text-600 mb-5">You do not have the necessary permisions. Please contact
|
||||
admins.</span>
|
||||
<img src="/demo/images/access/asset-access.svg" alt="Access denied" class="mb-5" width="80%" />
|
||||
<div class="col-12 mt-5 text-center">
|
||||
<i class="pi pi-fw pi-arrow-left text-blue-500 mr-2" style="vertical-align: center"></i>
|
||||
@@ -24,5 +27,4 @@ import AppConfig from '@/layout/AppConfig.vue';
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<AppConfig simple />
|
||||
</template>
|
||||
|
||||
@@ -1,15 +1,17 @@
|
||||
<script setup>
|
||||
import AppConfig from '@/layout/AppConfig.vue';
|
||||
</script>
|
||||
<script setup></script>
|
||||
|
||||
<template>
|
||||
<div class="surface-ground flex align-items-center justify-content-center min-h-screen min-w-screen overflow-hidden">
|
||||
<div
|
||||
class="surface-ground flex align-items-center justify-content-center min-h-screen min-w-screen overflow-hidden">
|
||||
<div class="flex flex-column align-items-center justify-content-center">
|
||||
<img src="/demo/images/error/logo-error.svg" alt="Sakai logo" class="mb-5 w-6rem flex-shrink-0" />
|
||||
<div style="border-radius: 56px; padding: 0.3rem; background: linear-gradient(180deg, rgba(233, 30, 99, 0.4) 10%, rgba(33, 150, 243, 0) 30%)">
|
||||
<div class="w-full surface-card py-8 px-5 sm:px-8 flex flex-column align-items-center" style="border-radius: 53px">
|
||||
<div
|
||||
style="border-radius: 56px; padding: 0.3rem; background: linear-gradient(180deg, rgba(233, 30, 99, 0.4) 10%, rgba(33, 150, 243, 0) 30%)">
|
||||
<div class="w-full surface-card py-8 px-5 sm:px-8 flex flex-column align-items-center"
|
||||
style="border-radius: 53px">
|
||||
<div class="grid flex flex-column align-items-center">
|
||||
<div class="flex justify-content-center align-items-center bg-pink-500 border-circle" style="height: 3.2rem; width: 3.2rem">
|
||||
<div class="flex justify-content-center align-items-center bg-pink-500 border-circle"
|
||||
style="height: 3.2rem; width: 3.2rem">
|
||||
<i class="pi pi-fw pi-exclamation-circle text-2xl text-white"></i>
|
||||
</div>
|
||||
<h1 class="text-900 font-bold text-5xl mb-2">Error Occured</h1>
|
||||
@@ -24,5 +26,4 @@ import AppConfig from '@/layout/AppConfig.vue';
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<AppConfig simple />
|
||||
</template>
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<script setup>
|
||||
import { useLayout } from '@/layout/composables/layout';
|
||||
import { ref, computed } from 'vue';
|
||||
import AppConfig from '@/layout/AppConfig.vue';
|
||||
|
||||
const { layoutConfig } = useLayout();
|
||||
const email = ref('');
|
||||
@@ -14,10 +13,12 @@ const logoUrl = computed(() => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="surface-ground flex align-items-center justify-content-center min-h-screen min-w-screen overflow-hidden">
|
||||
<div
|
||||
class="surface-ground flex align-items-center justify-content-center min-h-screen min-w-screen overflow-hidden">
|
||||
<div class="flex flex-column align-items-center justify-content-center">
|
||||
<img :src="logoUrl" alt="Sakai logo" class="mb-5 w-6rem flex-shrink-0" />
|
||||
<div style="border-radius: 56px; padding: 0.3rem; background: linear-gradient(180deg, var(--primary-color) 10%, rgba(33, 150, 243, 0) 30%)">
|
||||
<div
|
||||
style="border-radius: 56px; padding: 0.3rem; background: linear-gradient(180deg, var(--primary-color) 10%, rgba(33, 150, 243, 0) 30%)">
|
||||
<div class="w-full surface-card py-8 px-5 sm:px-8" style="border-radius: 53px">
|
||||
<div class="text-center mb-5">
|
||||
<img src="/demo/images/login/avatar.png" alt="Image" height="50" class="mb-3" />
|
||||
@@ -27,17 +28,20 @@ const logoUrl = computed(() => {
|
||||
|
||||
<div>
|
||||
<label for="email1" class="block text-900 text-xl font-medium mb-2">Email</label>
|
||||
<InputText id="email1" type="text" placeholder="Email address" class="w-full md:w-30rem mb-5" style="padding: 1rem" v-model="email" />
|
||||
<InputText id="email1" type="text" placeholder="Email address" class="w-full md:w-30rem mb-5"
|
||||
style="padding: 1rem" v-model="email" />
|
||||
|
||||
<label for="password1" class="block text-900 font-medium text-xl mb-2">Password</label>
|
||||
<Password id="password1" v-model="password" placeholder="Password" :toggleMask="true" class="w-full mb-3" inputClass="w-full" :inputStyle="{ padding: '1rem' }"></Password>
|
||||
<Password id="password1" v-model="password" placeholder="Password" :toggleMask="true"
|
||||
class="w-full mb-3" inputClass="w-full" :inputStyle="{ padding: '1rem' }"></Password>
|
||||
|
||||
<div class="flex align-items-center justify-content-between mb-5 gap-5">
|
||||
<div class="flex align-items-center">
|
||||
<Checkbox v-model="checked" id="rememberme1" binary class="mr-2"></Checkbox>
|
||||
<label for="rememberme1">Remember me</label>
|
||||
</div>
|
||||
<a class="font-medium no-underline ml-2 text-right cursor-pointer" style="color: var(--primary-color)">Forgot password?</a>
|
||||
<a class="font-medium no-underline ml-2 text-right cursor-pointer"
|
||||
style="color: var(--primary-color)">Forgot password?</a>
|
||||
</div>
|
||||
<Button label="Sign In" class="w-full p-3 text-xl"></Button>
|
||||
</div>
|
||||
@@ -45,7 +49,6 @@ const logoUrl = computed(() => {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<AppConfig simple />
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script setup>
|
||||
import { ref, onBeforeMount, reactive } from 'vue';
|
||||
import { FilterMatchMode, FilterOperator } from 'primevue/api';
|
||||
import { FilterMatchMode, FilterOperator } from '@primevue/core/api';
|
||||
import { CustomerService } from '@/service/CustomerService';
|
||||
import { ProductService } from '@/service/ProductService';
|
||||
|
||||
@@ -128,25 +128,18 @@ const calculateCustomerTotal = (name) => {
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
<h5>Filter Menu</h5>
|
||||
<DataTable
|
||||
:value="customer1"
|
||||
:paginator="true"
|
||||
:rows="10"
|
||||
dataKey="id"
|
||||
:rowHover="true"
|
||||
v-model:filters="filters1"
|
||||
filterDisplay="menu"
|
||||
:loading="loading1"
|
||||
:filters="filters1"
|
||||
<DataTable :value="customer1" :paginator="true" :rows="10" dataKey="id" :rowHover="true"
|
||||
v-model:filters="filters1" filterDisplay="menu" :loading="loading1" :filters="filters1"
|
||||
:globalFilterFields="['name', 'country.name', 'representative.name', 'balance', 'status']"
|
||||
showGridlines
|
||||
>
|
||||
showGridlines>
|
||||
<template #header>
|
||||
<div class="flex justify-content-between flex-column sm:flex-row">
|
||||
<Button type="button" icon="pi pi-filter-slash" label="Clear" outlined @click="clearFilter1()" />
|
||||
<Button type="button" icon="pi pi-filter-slash" label="Clear" outlined
|
||||
@click="clearFilter1()" />
|
||||
<IconField iconPosition="left">
|
||||
<InputIcon class="pi pi-search" />
|
||||
<InputText v-model="filters1['global'].value" placeholder="Keyword Search" style="width: 100%" />
|
||||
<InputText v-model="filters1['global'].value" placeholder="Keyword Search"
|
||||
style="width: 100%" />
|
||||
</IconField>
|
||||
</div>
|
||||
</template>
|
||||
@@ -157,40 +150,52 @@ const calculateCustomerTotal = (name) => {
|
||||
{{ data.name }}
|
||||
</template>
|
||||
<template #filter="{ filterModel }">
|
||||
<InputText type="text" v-model="filterModel.value" class="p-column-filter" placeholder="Search by name" />
|
||||
<InputText type="text" v-model="filterModel.value" class="p-column-filter"
|
||||
placeholder="Search by name" />
|
||||
</template>
|
||||
</Column>
|
||||
<Column header="Country" filterField="country.name" style="min-width: 12rem">
|
||||
<template #body="{ data }">
|
||||
<div class="flex align-items-center gap-2">
|
||||
<img alt="flag" src="/demo/images/flag/flag_placeholder.png" :class="`flag flag-${data.country.code}`" style="width: 24px" />
|
||||
<img alt="flag" src="/demo/images/flag/flag_placeholder.png"
|
||||
:class="`flag flag-${data.country.code}`" style="width: 24px" />
|
||||
<span>{{ data.country.name }}</span>
|
||||
</div>
|
||||
</template>
|
||||
<template #filter="{ filterModel }">
|
||||
<InputText type="text" v-model="filterModel.value" class="p-column-filter" placeholder="Search by country" />
|
||||
<InputText type="text" v-model="filterModel.value" class="p-column-filter"
|
||||
placeholder="Search by country" />
|
||||
</template>
|
||||
<template #filterclear="{ filterCallback }">
|
||||
<Button type="button" icon="pi pi-times" @click="filterCallback()" severity="secondary"></Button>
|
||||
<Button type="button" icon="pi pi-times" @click="filterCallback()"
|
||||
severity="secondary"></Button>
|
||||
</template>
|
||||
<template #filterapply="{ filterCallback }">
|
||||
<Button type="button" icon="pi pi-check" @click="filterCallback()" severity="success"></Button>
|
||||
<Button type="button" icon="pi pi-check" @click="filterCallback()"
|
||||
severity="success"></Button>
|
||||
</template>
|
||||
</Column>
|
||||
<Column header="Agent" filterField="representative" :showFilterMatchModes="false" :filterMenuStyle="{ width: '14rem' }" style="min-width: 14rem">
|
||||
<Column header="Agent" filterField="representative" :showFilterMatchModes="false"
|
||||
:filterMenuStyle="{ width: '14rem' }" style="min-width: 14rem">
|
||||
<template #body="{ data }">
|
||||
<div class="flex align-items-center gap-2">
|
||||
<img :alt="data.representative.name" :src="`https://primefaces.org/cdn/primevue/images/avatar/${data.representative.image}`" style="width: 32px" />
|
||||
<img :alt="data.representative.name"
|
||||
:src="`https://primefaces.org/cdn/primevue/images/avatar/${data.representative.image}`"
|
||||
style="width: 32px" />
|
||||
<span>{{ data.representative.name }}</span>
|
||||
</div>
|
||||
</template>
|
||||
<template #filter="{ filterModel }">
|
||||
<div class="mb-3 text-bold">Agent Picker</div>
|
||||
<MultiSelect v-model="filterModel.value" :options="representatives" optionLabel="name" placeholder="Any" class="p-column-filter">
|
||||
<MultiSelect v-model="filterModel.value" :options="representatives" optionLabel="name"
|
||||
placeholder="Any" class="p-column-filter">
|
||||
<template #option="slotProps">
|
||||
<div class="p-multiselect-representative-option">
|
||||
<img :alt="slotProps.option.name" :src="'/demo/images/avatar/' + slotProps.option.image" width="32" style="vertical-align: middle" />
|
||||
<span style="margin-left: 0.5em; vertical-align: middle" class="image-text">{{ slotProps.option.name }}</span>
|
||||
<img :alt="slotProps.option.name"
|
||||
:src="'/demo/images/avatar/' + slotProps.option.image" width="32"
|
||||
style="vertical-align: middle" />
|
||||
<span style="margin-left: 0.5em; vertical-align: middle" class="image-text">{{
|
||||
slotProps.option.name }}</span>
|
||||
</div>
|
||||
</template>
|
||||
</MultiSelect>
|
||||
@@ -212,18 +217,22 @@ const calculateCustomerTotal = (name) => {
|
||||
<InputNumber v-model="filterModel.value" mode="currency" currency="USD" locale="en-US" />
|
||||
</template>
|
||||
</Column>
|
||||
<Column field="status" header="Status" :filterMenuStyle="{ width: '14rem' }" style="min-width: 12rem">
|
||||
<Column field="status" header="Status" :filterMenuStyle="{ width: '14rem' }"
|
||||
style="min-width: 12rem">
|
||||
<template #body="{ data }">
|
||||
<Tag :severity="getSeverity(data.status)">{{ data.status.toUpperCase() }}</Tag>
|
||||
</template>
|
||||
<template #filter="{ filterModel }">
|
||||
<Dropdown v-model="filterModel.value" :options="statuses" placeholder="Any" class="p-column-filter" :showClear="true">
|
||||
<Dropdown v-model="filterModel.value" :options="statuses" placeholder="Any"
|
||||
class="p-column-filter" :showClear="true">
|
||||
<template #value="slotProps">
|
||||
<Tag :severity="getSeverity(slotProps.value)" v-if="slotProps.value">{{ slotProps.value }} </Tag>
|
||||
<Tag :severity="getSeverity(slotProps.value)" v-if="slotProps.value">{{
|
||||
slotProps.value }} </Tag>
|
||||
<span v-else>{{ slotProps.placeholder }}</span>
|
||||
</template>
|
||||
<template #option="slotProps">
|
||||
<Tag :severity="getSeverity(slotProps.option)">{{ slotProps.option.toUpperCase() }}</Tag>
|
||||
<Tag :severity="getSeverity(slotProps.option)">{{ slotProps.option.toUpperCase() }}
|
||||
</Tag>
|
||||
</template>
|
||||
</Dropdown>
|
||||
</template>
|
||||
@@ -240,9 +249,11 @@ const calculateCustomerTotal = (name) => {
|
||||
</div>
|
||||
</template>
|
||||
</Column>
|
||||
<Column field="verified" header="Verified" dataType="boolean" bodyClass="text-center" style="min-width: 8rem">
|
||||
<Column field="verified" header="Verified" dataType="boolean" bodyClass="text-center"
|
||||
style="min-width: 8rem">
|
||||
<template #body="{ data }">
|
||||
<i class="pi" :class="{ 'text-green-500 pi-check-circle': data.verified, 'text-pink-500 pi-times-circle': !data.verified }"></i>
|
||||
<i class="pi"
|
||||
:class="{ 'text-green-500 pi-check-circle': data.verified, 'text-pink-500 pi-times-circle': !data.verified }"></i>
|
||||
</template>
|
||||
<template #filter="{ filterModel }">
|
||||
<TriStateCheckbox v-model="filterModel.value" />
|
||||
@@ -255,15 +266,18 @@ const calculateCustomerTotal = (name) => {
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
<h5>Frozen Columns</h5>
|
||||
<ToggleButton v-model="idFrozen" onIcon="pi pi-lock" offIcon="pi pi-lock-open" onLabel="Unfreeze Id" offLabel="Freeze Id" style="width: 10rem" />
|
||||
<ToggleButton v-model="idFrozen" onIcon="pi pi-lock" offIcon="pi pi-lock-open" onLabel="Unfreeze Id"
|
||||
offLabel="Freeze Id" style="width: 10rem" />
|
||||
|
||||
<DataTable :value="customer2" :scrollable="true" scrollHeight="400px" :loading="loading2" scrollDirection="both" class="mt-3">
|
||||
<DataTable :value="customer2" :scrollable="true" scrollHeight="400px" :loading="loading2"
|
||||
scrollDirection="both" class="mt-3">
|
||||
<Column field="name" header="Name" style="min-width: 200px" frozen></Column>
|
||||
<Column field="id" header="Id" style="min-width: 100px" :frozen="idFrozen"></Column>
|
||||
<Column field="country.name" header="Country" :style="{ width: '200px' }">
|
||||
<template #body="{ data }">
|
||||
<div class="flex align-items-center gap-2">
|
||||
<img alt="flag" src="/demo/images/flag/flag_placeholder.png" :class="`flag flag-${data.country.code}`" style="width: 24px" />
|
||||
<img alt="flag" src="/demo/images/flag/flag_placeholder.png"
|
||||
:class="`flag flag-${data.country.code}`" style="width: 24px" />
|
||||
<span>{{ data.country.name }}</span>
|
||||
</div>
|
||||
</template>
|
||||
@@ -279,7 +293,9 @@ const calculateCustomerTotal = (name) => {
|
||||
<Column field="representative.name" header="Representative" style="min-width: 200px">
|
||||
<template #body="{ data }">
|
||||
<div class="flex align-items-center gap-2">
|
||||
<img :alt="data.representative.name" :src="`https://primefaces.org/cdn/primevue/images/avatar/${data.representative.image}`" style="width: 32px" />
|
||||
<img :alt="data.representative.name"
|
||||
:src="`https://primefaces.org/cdn/primevue/images/avatar/${data.representative.image}`"
|
||||
style="width: 32px" />
|
||||
<span>{{ data.representative.name }}</span>
|
||||
</div>
|
||||
</template>
|
||||
@@ -296,7 +312,8 @@ const calculateCustomerTotal = (name) => {
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
<h5>Row Expand</h5>
|
||||
<DataTable :value="products" v-model:expandedRows="expandedRows" dataKey="id" tableStyle="min-width: 60rem">
|
||||
<DataTable :value="products" v-model:expandedRows="expandedRows" dataKey="id"
|
||||
tableStyle="min-width: 60rem">
|
||||
<template #header>
|
||||
<div>
|
||||
<Button icon="pi pi-plus" label="Expand All" @click="expandAll" class="mr-2 mb-2" />
|
||||
@@ -311,7 +328,8 @@ const calculateCustomerTotal = (name) => {
|
||||
</Column>
|
||||
<Column header="Image">
|
||||
<template #body="slotProps">
|
||||
<img :src="'/demo/images/product/' + slotProps.data.image" :alt="slotProps.data.image" class="shadow-2" width="100" />
|
||||
<img :src="'/demo/images/product/' + slotProps.data.image" :alt="slotProps.data.image"
|
||||
class="shadow-2" width="100" />
|
||||
</template>
|
||||
</Column>
|
||||
<Column field="price" header="Price" :sortable="true">
|
||||
@@ -322,8 +340,8 @@ const calculateCustomerTotal = (name) => {
|
||||
<Column field="category" header="Category" :sortable="true">
|
||||
<template #body="slotProps">
|
||||
{{ formatCurrency(slotProps.data.category) }}
|
||||
</template></Column
|
||||
>
|
||||
</template>
|
||||
</Column>
|
||||
<Column field="rating" header="Reviews" :sortable="true">
|
||||
<template #body="slotProps">
|
||||
<Rating :modelValue="slotProps.data.rating" :readonly="true" :cancel="false" />
|
||||
@@ -331,7 +349,8 @@ const calculateCustomerTotal = (name) => {
|
||||
</Column>
|
||||
<Column field="inventoryStatus" header="Status" :sortable="true">
|
||||
<template #body="slotProps">
|
||||
<Tag :severity="getBadgeSeverity(slotProps.data.inventoryStatus)">{{ slotProps.data.inventoryStatus }}</Tag>
|
||||
<Tag :severity="getBadgeSeverity(slotProps.data.inventoryStatus)">{{
|
||||
slotProps.data.inventoryStatus }}</Tag>
|
||||
</template>
|
||||
</Column>
|
||||
<template #expansion="slotProps">
|
||||
@@ -360,7 +379,9 @@ const calculateCustomerTotal = (name) => {
|
||||
</Column>
|
||||
<Column field="status" header="Status" :sortable="true">
|
||||
<template #body="slotProps">
|
||||
<span :class="'order-badge order-' + (slotProps.data.status ? slotProps.data.status.toLowerCase() : '')">{{ slotProps.data.status }}</span>
|
||||
<span
|
||||
:class="'order-badge order-' + (slotProps.data.status ? slotProps.data.status.toLowerCase() : '')">{{
|
||||
slotProps.data.status }}</span>
|
||||
</template>
|
||||
</Column>
|
||||
<Column headerStyle="width:4rem">
|
||||
@@ -378,13 +399,15 @@ const calculateCustomerTotal = (name) => {
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
<h5>Subheader Grouping</h5>
|
||||
<DataTable :value="customer3" rowGroupMode="subheader" groupRowsBy="representative.name" sortMode="single" sortField="representative.name" :sortOrder="1" scrollable scrollHeight="400px">
|
||||
<DataTable :value="customer3" rowGroupMode="subheader" groupRowsBy="representative.name"
|
||||
sortMode="single" sortField="representative.name" :sortOrder="1" scrollable scrollHeight="400px">
|
||||
<Column field="representative.name" header="Representative"></Column>
|
||||
<Column field="name" header="Name" style="min-width: 200px"></Column>
|
||||
<Column field="country" header="Country" style="min-width: 200px">
|
||||
<template #body="{ data }">
|
||||
<div class="flex align-items-center gap-2">
|
||||
<img alt="flag" src="/demo/images/flag/flag_placeholder.png" :class="`flag flag-${data.country.code}`" style="width: 24px" />
|
||||
<img alt="flag" src="/demo/images/flag/flag_placeholder.png"
|
||||
:class="`flag flag-${data.country.code}`" style="width: 24px" />
|
||||
<span>{{ data.country.name }}</span>
|
||||
</div>
|
||||
</template>
|
||||
@@ -392,18 +415,22 @@ const calculateCustomerTotal = (name) => {
|
||||
<Column field="company" header="Company" style="min-width: 200px"></Column>
|
||||
<Column field="status" header="Status" style="min-width: 200px">
|
||||
<template #body="slotProps">
|
||||
<Tag :severity="getSeverity(slotProps.data.status)">{{ slotProps.data.status.toUpperCase() }}</Tag>
|
||||
<Tag :severity="getSeverity(slotProps.data.status)">{{ slotProps.data.status.toUpperCase()
|
||||
}}</Tag>
|
||||
</template>
|
||||
</Column>
|
||||
<Column field="date" header="Date" style="min-width: 200px"></Column>
|
||||
<template #groupheader="slotProps">
|
||||
<div class="flex align-items-center gap-2">
|
||||
<img :alt="slotProps.data.representative.name" :src="'/demo/images/avatar/' + slotProps.data.representative.image" width="32" style="vertical-align: middle" />
|
||||
<img :alt="slotProps.data.representative.name"
|
||||
:src="'/demo/images/avatar/' + slotProps.data.representative.image" width="32"
|
||||
style="vertical-align: middle" />
|
||||
<span>{{ slotProps.data.representative.name }}</span>
|
||||
</div>
|
||||
</template>
|
||||
<template #groupfooter="slotProps">
|
||||
<td style="text-align: right" class="text-bold pr-6">Total Customers: {{ calculateCustomerTotal(slotProps.data.representative.name) }}</td>
|
||||
<td style="text-align: right" class="text-bold pr-6">Total Customers: {{
|
||||
calculateCustomerTotal(slotProps.data.representative.name) }}</td>
|
||||
</template>
|
||||
</DataTable>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user