Initial commit

This commit is contained in:
andrea.terzani
2024-07-31 09:22:52 +02:00
commit 8dd4417d0e
205 changed files with 28657 additions and 0 deletions

7
src/App.vue Normal file
View File

@@ -0,0 +1,7 @@
<script setup></script>
<template>
<router-view />
</template>
<style scoped></style>

15
src/assets/demo/code.scss Normal file
View File

@@ -0,0 +1,15 @@
pre.app-code {
background-color: var(--surface-ground);
margin: 0 0 1rem 0;
padding: 0;
border-radius: var(--border-radius);
overflow: auto;
code {
color: var(--surface-900);
padding: 1rem;
line-height: 1.5;
display: block;
font-family: monaco, Consolas, monospace;
}
}

View File

@@ -0,0 +1,2 @@
@import './flags/flags.css';
@import './code.scss';

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

View File

@@ -0,0 +1,12 @@
.layout-main-container {
display: flex;
flex-direction: column;
min-height: 100vh;
justify-content: space-between;
padding: 6rem 2rem 2rem 4rem;
transition: margin-left var(--layout-section-transition-duration);
}
.layout-main {
flex: 1 1 auto;
}

View File

@@ -0,0 +1,8 @@
.layout-footer {
transition: margin-left var(--layout-section-transition-duration);
display: flex;
align-items: center;
justify-content: center;
padding-top: 1rem;
border-top: 1px solid var(--surface-border);
}

View File

@@ -0,0 +1,23 @@
html {
height: 100%;
font-size: 14px;
}
body {
font-family: 'CircularStd', sans-serif;
color: var(--text-color);
background-color: var(--surface-ground);
margin: 0;
padding: 0;
min-height: 100%;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
a {
text-decoration: none;
}
.layout-wrapper {
min-height: 100vh;
}

View File

@@ -0,0 +1,158 @@
.layout-sidebar {
position: fixed;
width: 300px;
height: calc(100vh - 9rem);
z-index: 999;
overflow-y: auto;
user-select: none;
top: 6rem;
left: 2rem;
transition:
transform var(--layout-section-transition-duration),
left var(--layout-section-transition-duration);
background-color: var(--surface-overlay);
border-radius: var(--content-border-radius);
padding: 0.5rem 1.5rem;
}
.layout-menu {
margin: 0;
padding: 0;
list-style-type: none;
.layout-root-menuitem {
> .layout-menuitem-root-text {
font-size: 0.857rem;
text-transform: uppercase;
font-weight: 700;
color: var(--text-color);
margin: 0.75rem 0;
}
> a {
display: none;
}
}
a {
user-select: none;
&.active-menuitem {
> .layout-submenu-toggler {
transform: rotate(-180deg);
}
}
}
li.active-menuitem {
> a {
.layout-submenu-toggler {
transform: rotate(-180deg);
}
}
}
ul {
margin: 0;
padding: 0;
list-style-type: none;
a {
display: flex;
align-items: center;
position: relative;
outline: 0 none;
color: var(--text-color);
cursor: pointer;
padding: 0.75rem 1rem;
border-radius: var(--content-border-radius);
transition:
background-color var(--element-transition-duration),
box-shadow var(--element-transition-duration);
.layout-menuitem-icon {
margin-right: 0.5rem;
}
.layout-submenu-toggler {
font-size: 75%;
margin-left: auto;
transition: transform var(--element-transition-duration);
}
&.active-route {
font-weight: 700;
color: var(--primary-color);
}
&:hover {
background-color: var(--surface-hover);
}
&:focus {
@include focused-inset();
}
}
ul {
overflow: hidden;
border-radius: var(--content-border-radius);
li {
a {
margin-left: 1rem;
}
li {
a {
margin-left: 2rem;
}
li {
a {
margin-left: 2.5rem;
}
li {
a {
margin-left: 3rem;
}
li {
a {
margin-left: 3.5rem;
}
li {
a {
margin-left: 4rem;
}
}
}
}
}
}
}
}
}
}
.layout-submenu-enter-from,
.layout-submenu-leave-to {
max-height: 0;
}
.layout-submenu-enter-to,
.layout-submenu-leave-from {
max-height: 1000px;
}
.layout-submenu-leave-active {
overflow: hidden;
transition: max-height 0.45s cubic-bezier(0, 1, 0, 1);
}
.layout-submenu-enter-active {
overflow: hidden;
transition: max-height 1s ease-in-out;
}

View File

@@ -0,0 +1,15 @@
@mixin focused() {
outline-width: var(--focus-ring-width);
outline-style: var(--focus-ring-style);
outline-color: var(--focus-ring-color);
outline-offset: var(--focus-ring-offset);
box-shadow: var(--focus-ring-shadow);
transition:
box-shadow var(--transition-duration),
outline-color var(--transition-duration);
}
@mixin focused-inset() {
outline-offset: -1px;
box-shadow: inset var(--focus-ring-shadow);
}

View File

@@ -0,0 +1,47 @@
.preloader {
position: fixed;
z-index: 999999;
background: #edf1f5;
width: 100%;
height: 100%;
}
.preloader-content {
border: 0 solid transparent;
border-radius: 50%;
width: 150px;
height: 150px;
position: absolute;
top: calc(50vh - 75px);
left: calc(50vw - 75px);
}
.preloader-content:before, .preloader-content:after{
content: '';
border: 1em solid var(--primary-color);
border-radius: 50%;
width: inherit;
height: inherit;
position: absolute;
top: 0;
left: 0;
animation: loader 2s linear infinite;
opacity: 0;
}
.preloader-content:before{
animation-delay: 0.5s;
}
@keyframes loader{
0%{
transform: scale(0);
opacity: 0;
}
50%{
opacity: 1;
}
100%{
transform: scale(1);
opacity: 0;
}
}

View File

@@ -0,0 +1,104 @@
@media screen and (min-width: 1960px) {
.layout-main,
.landing-wrapper {
width: 1504px;
margin-left: auto !important;
margin-right: auto !important;
}
}
@media (min-width: 992px) {
.layout-wrapper {
&.layout-overlay {
.layout-main-container {
margin-left: 0;
padding-left: 2rem;
}
.layout-sidebar {
transform: translateX(-100%);
left: 0;
top: 0;
height: 100vh;
border-top-left-radius: 0;
border-bottom-left-radius: 0;
box-shadow:
0px 3px 5px rgba(0, 0, 0, 0.02),
0px 0px 2px rgba(0, 0, 0, 0.05),
0px 1px 4px rgba(0, 0, 0, 0.08);
}
&.layout-overlay-active {
.layout-sidebar {
transform: translateX(0);
}
}
}
&.layout-static {
.layout-main-container {
margin-left: 300px;
}
&.layout-static-inactive {
.layout-sidebar {
transform: translateX(-100%);
left: 0;
}
.layout-main-container {
margin-left: 0;
padding-left: 2rem;
}
}
}
.layout-mask {
display: none;
}
}
}
@media (max-width: 991px) {
.blocked-scroll {
overflow: hidden;
}
.layout-wrapper {
.layout-main-container {
margin-left: 0;
padding-left: 2rem;
}
.layout-sidebar {
transform: translateX(-100%);
left: 0;
top: 0;
height: 100vh;
border-top-left-radius: 0;
border-bottom-left-radius: 0;
}
.layout-mask {
display: none;
position: fixed;
top: 0;
left: 0;
z-index: 998;
width: 100%;
height: 100%;
background-color: var(--maskbg);
}
&.layout-mobile-active {
.layout-sidebar {
transform: translateX(0);
}
.layout-mask {
display: block;
animation: fadein var(--layout-section-transition-duration);
}
}
}
}

View File

@@ -0,0 +1,223 @@
.layout-topbar {
position: fixed;
height: 4rem;
z-index: 997;
left: 0;
top: 0;
width: 100%;
padding: 0 2rem;
background-color: var(--surface-card);
transition: left var(--layout-section-transition-duration);
display: flex;
align-items: center;
.layout-topbar-logo-container {
width: 300px;
display: flex;
align-items: center;
}
.layout-topbar-logo {
display: inline-flex;
align-items: center;
font-size: 1.5rem;
border-radius: var(--content-border-radius);
color: var(--text-color);
font-weight: 500;
gap: 0.5rem;
svg {
width: 3rem;
}
&:focus-visible {
@include focused();
}
}
.layout-topbar-action {
display: inline-flex;
justify-content: center;
align-items: center;
color: var(--text-color-secondary);
border-radius: 50%;
width: 2.5rem;
height: 2.5rem;
color: var(--text-color);
transition: background-color var(--element-transition-duration);
cursor: pointer;
&:hover {
background-color: var(--surface-hover);
}
&:focus-visible {
@include focused();
}
i {
font-size: 1.25rem;
}
span {
font-size: 1rem;
display: none;
}
&.layout-topbar-action-highlight {
background-color: var(--primary-color);
color: var(--primary-contrast-color);
}
}
.layout-menu-button {
margin-left: 2rem;
}
.layout-topbar-menu-button {
display: none;
}
.layout-topbar-actions {
margin-left: auto;
display: flex;
gap: 1rem;
}
.layout-topbar-menu-content {
display: flex;
gap: 1rem;
}
.layout-config-menu {
display: flex;
gap: 1rem;
}
}
@media (max-width: 991px) {
.layout-topbar {
.layout-topbar-logo-container {
width: auto;
order: 2;
}
.layout-menu-button {
margin-left: 0;
margin-right: 1rem;
order: 1;
}
.layout-topbar-menu-button {
display: inline-flex;
order: 4;
}
.layout-topbar-actions {
order: 3;
}
.layout-topbar-menu {
position: absolute;
background-color: var(--surface-overlay);
transform-origin: top;
box-shadow:
0px 3px 5px rgba(0, 0, 0, 0.02),
0px 0px 2px rgba(0, 0, 0, 0.05),
0px 1px 4px rgba(0, 0, 0, 0.08);
border-radius: var(--content-border-radius);
padding: 1rem;
right: 2rem;
top: 4rem;
min-width: 15rem;
.layout-topbar-menu-content {
gap: 0.5rem;
}
.layout-topbar-action {
display: flex;
width: 100%;
height: auto;
justify-content: flex-start;
border-radius: var(--content-border-radius);
padding: 0.5rem 1rem;
i {
font-size: 1rem;
margin-right: 0.5rem;
}
span {
font-weight: medium;
display: block;
}
}
}
.layout-topbar-menu-content {
flex-direction: column;
}
}
}
.config-panel {
position: absolute;
top: 3.25rem;
right: 0;
width: 16rem;
padding: 0.75rem;
background-color: var(--surface-overlay);
border-radius: 6px;
border: 1px solid var(--surface-border);
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: 0.875rem;
color: var(--text-secondary-color);
font-weight: 600;
line-height: 1;
}
.config-panel-colors {
> div {
padding-top: 0.5rem;
display: flex;
gap: 0.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;
}
}

View File

@@ -0,0 +1,68 @@
h1,
h2,
h3,
h4,
h5,
h6 {
margin: 1.5rem 0 1rem 0;
font-family: inherit;
font-weight: 700;
line-height: 1.5;
color: var(--text-color);
&:first-child {
margin-top: 0;
}
}
h1 {
font-size: 2.5rem;
}
h2 {
font-size: 2rem;
}
h3 {
font-size: 1.75rem;
}
h4 {
font-size: 1.5rem;
}
h5 {
font-size: 1.25rem;
}
h6 {
font-size: 1rem;
}
mark {
background: #fff8e1;
padding: 0.25rem 0.4rem;
border-radius: var(--content-border-radius);
font-family: monospace;
}
blockquote {
margin: 1rem 0;
padding: 0 2rem;
border-left: 4px solid #90a4ae;
}
hr {
border-top: solid var(--surface-border);
border-width: 1px 0 0 0;
margin: 1rem 0;
}
p {
margin: 0 0 1rem 0;
line-height: 1.5;
&:last-child {
margin-bottom: 0;
}
}

View File

@@ -0,0 +1,25 @@
/* Utils */
.clearfix:after {
content: ' ';
display: block;
clear: both;
}
.card {
background: var(--surface-card);
padding: 2rem;
margin-bottom: 2rem;
border-radius: var(--content-border-radius);
&:last-child {
margin-bottom: 0;
}
}
.p-toast {
&.p-toast-top-right,
&.p-toast-top-left,
&.p-toast-top-center {
top: 100px;
}
}

View File

@@ -0,0 +1,13 @@
@import './variables/_common';
@import './variables/_light';
@import './variables/_dark';
@import './_mixins';
@import './_preloading';
@import './_main';
@import './_topbar';
@import './_menu';
@import './_content';
@import './_footer';
@import './_responsive';
@import './_utils';
@import './_typography';

View File

@@ -0,0 +1,20 @@
:root {
--primary-color: var(--p-primary-color);
--primary-contrast-color: var(--p-primary-contrast-color);
--text-color: var(--p-text-color);
--text-color-secondary: var(--p-text-muted-color);
--surface-border: var(--p-content-border-color);
--surface-card: var(--p-content-background);
--surface-hover: var(--p-content-hover-background);
--surface-overlay: var(--p-overlay-popover-background);
--transition-duration: var(--p-transition-duration);
--maskbg: var(--p-mask-background);
--content-border-radius: var(--p-content-border-radius);
--layout-section-transition-duration: 0.2s;
--element-transition-duration: var(--p-transition-duration);
--focus-ring-width: var(--p-focus-ring-width);
--focus-ring-style: var(--p-focus-ring-style);
--focus-ring-color: var(--p-focus-ring-color);
--focus-ring-offset: var(--p-focus-ring-offset);
--focus-ring-shadow: var(--p-focus-ring-shadow);
}

View File

@@ -0,0 +1,3 @@
:root[class*='app-dark'] {
--surface-ground: var(--p-surface-950);
}

View File

@@ -0,0 +1,3 @@
:root {
--surface-ground: var(--p-surface-50);
}

5
src/assets/styles.scss Normal file
View File

@@ -0,0 +1,5 @@
/* You can add global styles to this file, and also import other style files */
@import '@/assets/layout/layout.scss';
@import 'primeicons/primeicons.css';
@import '@/assets/demo/demo.scss';

3
src/assets/tailwind.css Normal file
View File

@@ -0,0 +1,3 @@
@tailwind base;
@tailwind components;
@tailwind utilities;

View File

@@ -0,0 +1,212 @@
<script setup>
import { ref, reactive } from 'vue';
const props = defineProps({
header: {
type: String,
default: null
},
code: null,
recent: {
type: Boolean,
default: false
},
free: {
type: Boolean,
default: false
},
containerClass: null,
previewStyle: null
});
const BlockView = reactive({
PREVIEW: 0,
CODE: 1
});
const blockView = ref(0);
function activateView(event, blockViewValue) {
blockView.value = blockViewValue;
event.preventDefault();
}
async function copyCode(event) {
await navigator.clipboard.writeText(props.code);
event.preventDefault();
}
</script>
<template>
<div class="block-section">
<div class="block-header">
<span class="block-title">
<span>{{ header }}</span>
<span class="badge-new" v-if="recent">New</span>
<span class="badge-free" v-if="free">Free</span>
</span>
<div class="block-actions">
<a tabindex="0" :class="{ 'block-action-active': blockView === BlockView.PREVIEW }" @click="activateView($event, BlockView.PREVIEW)"><span>Preview</span></a>
<a :tabindex="'0'" :class="{ 'block-action-active': blockView === BlockView.CODE }" @click="activateView($event, BlockView.CODE)">
<span>Code</span>
</a>
<a :tabindex="0" class="block-action-copy" @click="copyCode($event)" v-tooltip.focus.bottom="{ value: 'Copied to clipboard' }"><i class="pi pi-copy"></i></a>
</div>
</div>
<div class="block-content">
<div :class="containerClass" :style="previewStyle" v-if="blockView == BlockView.PREVIEW">
<slot></slot>
</div>
<div v-if="blockView === BlockView.CODE">
<pre class="app-code"><code>{{code}}</code></pre>
</div>
</div>
</div>
</template>
<style scoped lang="scss">
.block-section {
margin-bottom: 4rem;
overflow: hidden;
}
.block-header {
padding: 1rem 2rem;
background-color: var(--surface-section);
border-top-left-radius: 12px;
border-top-right-radius: 12px;
border: 1px solid var(--surface-d);
display: flex;
align-items: center;
justify-content: space-between;
.block-title {
font-weight: 700;
display: inline-flex;
align-items: center;
.badge-free {
border-radius: 4px;
padding: 0.25rem 0.5rem;
background-color: var(--orange-500);
color: white;
margin-left: 1rem;
font-weight: 700;
font-size: 0.875rem;
}
}
.block-actions {
display: flex;
align-items: center;
justify-content: space-between;
user-select: none;
margin-left: 1rem;
a {
display: flex;
align-items: center;
margin-right: 0.75rem;
padding: 0.5rem 1rem;
border-radius: 4px;
font-weight: 600;
border: 1px solid transparent;
transition: background-color 0.2s;
cursor: pointer;
&:last-child {
margin-right: 0;
}
&:not(.block-action-disabled):hover {
background-color: var(--surface-c);
}
&.block-action-active {
border-color: var(--primary-color);
color: var(--primary-color);
}
&.block-action-copy {
i {
color: var(--primary-color);
font-size: 1.25rem;
}
}
&.block-action-disabled {
opacity: 0.6;
cursor: auto !important;
}
i {
margin-right: 0.5rem;
}
}
}
}
.block-content {
padding: 0;
border: 1px solid var(--surface-d);
border-top: 0 none;
border-bottom-left-radius: 12px;
border-bottom-right-radius: 12px;
overflow: hidden;
}
pre[class*='language-'] {
margin: 0 !important;
&:before,
&:after {
display: none !important;
}
code {
border-left: 0 none !important;
box-shadow: none !important;
background: var(--surface-e) !important;
margin: 0;
color: var(--text-color);
font-size: 14px;
padding: 0 2rem !important;
.token {
&.tag,
&.keyword {
color: #2196f3 !important;
}
&.attr-name,
&.attr-string {
color: #2196f3 !important;
}
&.attr-value {
color: #4caf50 !important;
}
&.punctuation {
color: var(--text-color);
}
&.operator,
&.string {
background: transparent;
}
}
}
}
@media screen and (max-width: 575px) {
.block-header {
flex-direction: column;
align-items: start;
.block-actions {
margin-top: 1rem;
margin-left: 0;
}
}
}
</style>

View File

@@ -0,0 +1,268 @@
<script setup>
import { useLayout } from '@/layout/composables/layout';
import { $t, updatePreset, updateSurfacePalette } from '@primevue/themes';
import Aura from '@primevue/themes/aura';
import Lara from '@primevue/themes/lara';
import Nora from '@primevue/themes/nora';
import { ref } from 'vue';
const { layoutConfig, setPrimary, setSurface, setPreset, isDarkTheme } = useLayout();
const preset = ref(layoutConfig.preset);
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);
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);
}
}
function onPresetChange(value) {
setPreset(value);
const presetValue = presets[value];
const surfacePalette = surfaces.value.find((s) => s.name === layoutConfig.surface)?.palette;
$t().preset(presetValue).preset(getPresetExt()).surfacePalette(surfacePalette).use({ useDefaultOptions: true });
}
</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': layoutConfig.primary === 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': layoutConfig.surface ? layoutConfig.surface === 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>

19
src/layout/AppFooter.vue Normal file
View File

@@ -0,0 +1,19 @@
<script setup>
import { useLayout } from '@/layout/composables/layout';
import { computed } from 'vue';
const { isDarkTheme } = useLayout();
const logoUrl = computed(() => {
return `/layout/images/${isDarkTheme ? 'logo-white' : 'logo-dark'}.svg`;
});
</script>
<template>
<div class="layout-footer">
APOLLO
by
<span class="font-medium ml-2">OlympusAI</span>
</div>
</template>
<style lang="scss" scoped></style>

72
src/layout/AppLayout.vue Normal file
View File

@@ -0,0 +1,72 @@
<script setup>
import { useLayout } from '@/layout/composables/layout';
import { computed, ref, watch } from 'vue';
import AppFooter from './AppFooter.vue';
import AppSidebar from './AppSidebar.vue';
import AppTopbar from './AppTopbar.vue';
const { layoutConfig, layoutState, isSidebarActive, resetMenu } = useLayout();
const outsideClickListener = ref(null);
watch(isSidebarActive, (newVal) => {
if (newVal) {
bindOutsideClickListener();
} else {
unbindOutsideClickListener();
}
});
const containerClass = computed(() => {
return {
'layout-theme-light': !layoutConfig.darkTheme,
'layout-theme-dark': layoutConfig.darkTheme,
'layout-overlay': layoutConfig.menuMode === 'overlay',
'layout-static': layoutConfig.menuMode === 'static',
'layout-static-inactive': layoutState.staticMenuDesktopInactive && layoutConfig.menuMode === 'static',
'layout-overlay-active': layoutState.overlayMenuActive,
'layout-mobile-active': layoutState.staticMenuMobileActive
};
});
const bindOutsideClickListener = () => {
if (!outsideClickListener.value) {
outsideClickListener.value = (event) => {
if (isOutsideClicked(event)) {
resetMenu();
}
};
document.addEventListener('click', outsideClickListener.value);
}
};
const unbindOutsideClickListener = () => {
if (outsideClickListener.value) {
document.removeEventListener('click', outsideClickListener);
outsideClickListener.value = null;
}
};
const isOutsideClicked = (event) => {
const sidebarEl = document.querySelector('.layout-sidebar');
const topbarEl = document.querySelector('.layout-menu-button');
return !(sidebarEl.isSameNode(event.target) || sidebarEl.contains(event.target) || topbarEl.isSameNode(event.target) || topbarEl.contains(event.target));
};
</script>
<template>
<div class="layout-wrapper" :class="containerClass">
<app-topbar></app-topbar>
<div class="layout-sidebar">
<app-sidebar></app-sidebar>
</div>
<div class="layout-main-container">
<div class="layout-main">
<router-view></router-view>
</div>
<app-footer></app-footer>
</div>
<div class="layout-mask"></div>
</div>
<Toast />
</template>
<style lang="scss" scoped></style>

29
src/layout/AppMenu.vue Normal file
View File

@@ -0,0 +1,29 @@
<script setup>
import { ref } from 'vue';
import AppMenuItem from './AppMenuItem.vue';
const model = ref([
{
label: 'Knowledge Source',
items: [{ label: 'Documents', icon: 'pi pi-fw pi-id-card', to: '/ksdocuments' },
{ label: 'Code Repository', icon: 'pi pi-fw pi-id-card', to: '/ks_code_repo' }
]
},
{
label: 'Vector Database',
items: [{ label: 'Dashboard', icon: 'pi pi-fw pi-home', to: '/' }]
},
]);
</script>
<template>
<ul class="layout-menu">
<template v-for="(item, i) in model" :key="item">
<app-menu-item v-if="!item.separator" :item="item" :index="i"></app-menu-item>
<li v-if="item.separator" class="menu-separator"></li>
</template>
</ul>
</template>
<style lang="scss" scoped></style>

View File

@@ -0,0 +1,91 @@
<script setup>
import { useLayout } from '@/layout/composables/layout';
import { onBeforeMount, ref, watch } from 'vue';
import { useRoute } from 'vue-router';
const route = useRoute();
const { layoutConfig, layoutState, setActiveMenuItem, onMenuToggle } = useLayout();
const props = defineProps({
item: {
type: Object,
default: () => ({})
},
index: {
type: Number,
default: 0
},
root: {
type: Boolean,
default: true
},
parentItemKey: {
type: String,
default: null
}
});
const isActiveMenu = ref(false);
const itemKey = ref(null);
onBeforeMount(() => {
itemKey.value = props.parentItemKey ? props.parentItemKey + '-' + props.index : String(props.index);
const activeItem = layoutState.activeMenuItem;
isActiveMenu.value = activeItem === itemKey.value || activeItem ? activeItem.startsWith(itemKey.value + '-') : false;
});
watch(
() => layoutConfig.activeMenuItem,
(newVal) => {
isActiveMenu.value = newVal === itemKey.value || newVal.startsWith(itemKey.value + '-');
}
);
const itemClick = (event, item) => {
if (item.disabled) {
event.preventDefault();
return;
}
if ((item.to || item.url) && (layoutState.staticMenuMobileActive || layoutState.overlayMenuActive)) {
onMenuToggle();
}
if (item.command) {
item.command({ originalEvent: event, item: item });
}
const foundItemKey = item.items ? (isActiveMenu.value ? props.parentItemKey : itemKey) : itemKey.value;
setActiveMenuItem(foundItemKey);
};
const checkActiveRoute = (item) => {
return route.path === item.to;
};
</script>
<template>
<li :class="{ 'layout-root-menuitem': root, 'active-menuitem': isActiveMenu }">
<div v-if="root && item.visible !== false" class="layout-menuitem-root-text">{{ item.label }}</div>
<a v-if="(!item.to || item.items) && item.visible !== false" :href="item.url" @click="itemClick($event, item, index)" :class="item.class" :target="item.target" tabindex="0">
<i :class="item.icon" class="layout-menuitem-icon"></i>
<span class="layout-menuitem-text">{{ item.label }}</span>
<i class="pi pi-fw pi-angle-down layout-submenu-toggler" v-if="item.items"></i>
</a>
<router-link v-if="item.to && !item.items && item.visible !== false" @click="itemClick($event, item, index)" :class="[item.class, { 'active-route': checkActiveRoute(item) }]" tabindex="0" :to="item.to">
<i :class="item.icon" class="layout-menuitem-icon"></i>
<span class="layout-menuitem-text">{{ item.label }}</span>
<i class="pi pi-fw pi-angle-down layout-submenu-toggler" v-if="item.items"></i>
</router-link>
<Transition v-if="item.items && item.visible !== false" name="layout-submenu">
<ul v-show="root ? true : isActiveMenu" class="layout-submenu">
<app-menu-item v-for="(child, i) in item.items" :key="child" :index="i" :item="child" :parentItemKey="itemKey" :root="false"></app-menu-item>
</ul>
</Transition>
</li>
</template>
<style lang="scss" scoped></style>

166
src/layout/AppMenuOld.vue Normal file
View File

@@ -0,0 +1,166 @@
<script setup>
import { ref } from 'vue';
import AppMenuItem from './AppMenuItem.vue';
const model = ref([
{
label: 'Knowledge Source Documents',
items: [{ label: 'Documents', icon: 'pi pi-fw pi-document', to: '/' }]
},
{
label: 'Home',
items: [{ label: 'Dashboard', icon: 'pi pi-fw pi-home', to: '/' }]
},
{
label: 'UI Components',
items: [
{ label: 'Form Layout', icon: 'pi pi-fw pi-id-card', to: '/uikit/formlayout' },
{ label: 'Input', icon: 'pi pi-fw pi-check-square', to: '/uikit/input' },
{ label: 'Button', icon: 'pi pi-fw pi-mobile', to: '/uikit/button', class: 'rotated-icon' },
{ label: 'Table', icon: 'pi pi-fw pi-table', to: '/uikit/table' },
{ label: 'List', icon: 'pi pi-fw pi-list', to: '/uikit/list' },
{ label: 'Tree', icon: 'pi pi-fw pi-share-alt', to: '/uikit/tree' },
{ label: 'Panel', icon: 'pi pi-fw pi-tablet', to: '/uikit/panel' },
{ label: 'Overlay', icon: 'pi pi-fw pi-clone', to: '/uikit/overlay' },
{ label: 'Media', icon: 'pi pi-fw pi-image', to: '/uikit/media' },
{ label: 'Menu', icon: 'pi pi-fw pi-bars', to: '/uikit/menu', preventExact: true },
{ label: 'Message', icon: 'pi pi-fw pi-comment', to: '/uikit/message' },
{ label: 'File', icon: 'pi pi-fw pi-file', to: '/uikit/file' },
{ label: 'Chart', icon: 'pi pi-fw pi-chart-bar', to: '/uikit/charts' },
{ label: 'Misc', icon: 'pi pi-fw pi-circle', to: '/uikit/misc' }
]
},
{
label: 'Utilities',
items: [
{ label: 'PrimeIcons', icon: 'pi pi-fw pi-prime', to: '/utilities/icons' },
{ label: 'PrimeFlex', icon: 'pi pi-fw pi-desktop', url: 'https://www.primefaces.org/primeflex/', target: '_blank' }
]
},
{
label: 'Pages',
icon: 'pi pi-fw pi-briefcase',
to: '/pages',
items: [
{
label: 'Landing',
icon: 'pi pi-fw pi-globe',
to: '/landing'
},
{
label: 'Auth',
icon: 'pi pi-fw pi-user',
items: [
{
label: 'Login',
icon: 'pi pi-fw pi-sign-in',
to: '/auth/login'
},
{
label: 'Error',
icon: 'pi pi-fw pi-times-circle',
to: '/auth/error'
},
{
label: 'Access Denied',
icon: 'pi pi-fw pi-lock',
to: '/auth/access'
}
]
},
{
label: 'Crud',
icon: 'pi pi-fw pi-pencil',
to: '/pages/crud'
},
{
label: 'Timeline',
icon: 'pi pi-fw pi-calendar',
to: '/pages/timeline'
},
{
label: 'Not Found',
icon: 'pi pi-fw pi-exclamation-circle',
to: '/pages/notfound'
},
{
label: 'Empty',
icon: 'pi pi-fw pi-circle-off',
to: '/pages/empty'
}
]
},
{
label: 'Hierarchy',
items: [
{
label: 'Submenu 1',
icon: 'pi pi-fw pi-bookmark',
items: [
{
label: 'Submenu 1.1',
icon: 'pi pi-fw pi-bookmark',
items: [
{ label: 'Submenu 1.1.1', icon: 'pi pi-fw pi-bookmark' },
{ label: 'Submenu 1.1.2', icon: 'pi pi-fw pi-bookmark' },
{ label: 'Submenu 1.1.3', icon: 'pi pi-fw pi-bookmark' }
]
},
{
label: 'Submenu 1.2',
icon: 'pi pi-fw pi-bookmark',
items: [{ label: 'Submenu 1.2.1', icon: 'pi pi-fw pi-bookmark' }]
}
]
},
{
label: 'Submenu 2',
icon: 'pi pi-fw pi-bookmark',
items: [
{
label: 'Submenu 2.1',
icon: 'pi pi-fw pi-bookmark',
items: [
{ label: 'Submenu 2.1.1', icon: 'pi pi-fw pi-bookmark' },
{ label: 'Submenu 2.1.2', icon: 'pi pi-fw pi-bookmark' }
]
},
{
label: 'Submenu 2.2',
icon: 'pi pi-fw pi-bookmark',
items: [{ label: 'Submenu 2.2.1', icon: 'pi pi-fw pi-bookmark' }]
}
]
}
]
},
{
label: 'Get Started',
items: [
{
label: 'Documentation',
icon: 'pi pi-fw pi-question',
to: '/documentation'
},
{
label: 'View Source',
icon: 'pi pi-fw pi-search',
url: 'https://github.com/primefaces/sakai-vue',
target: '_blank'
}
]
}
]);
</script>
<template>
<ul class="layout-menu">
<template v-for="(item, i) in model" :key="item">
<app-menu-item v-if="!item.separator" :item="item" :index="i"></app-menu-item>
<li v-if="item.separator" class="menu-separator"></li>
</template>
</ul>
</template>
<style lang="scss" scoped></style>

View File

@@ -0,0 +1,9 @@
<script setup>
import AppMenu from './AppMenu.vue';
</script>
<template>
<app-menu></app-menu>
</template>
<style lang="scss" scoped></style>

79
src/layout/AppTopbar.vue Normal file
View File

@@ -0,0 +1,79 @@
<script setup>
import { useLayout } from '@/layout/composables/layout';
import AppConfigurator from './AppConfigurator.vue';
const { onMenuToggle, toggleDarkMode, isDarkTheme } = useLayout();
</script>
<template>
<div class="layout-topbar">
<div class="layout-topbar-logo-container">
<router-link to="/" class="layout-topbar-logo">
<svg width="85" height="63" viewBox="0 0 85 63" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M27.017 30.3135C27.0057 30.5602 27 30.8085 27 31.0581C27 39.9267 34.1894 47.1161 43.0581 47.1161C51.9267 47.1161 59.1161 39.9267 59.1161 31.0581C59.1161 30.8026 59.1102 30.5485 59.0984 30.2959C60.699 30.0511 62.2954 29.7696 63.8864 29.4515L64.0532 29.4181C64.0949 29.9593 64.1161 30.5062 64.1161 31.0581C64.1161 42.6881 54.6881 52.1161 43.0581 52.1161C31.428 52.1161 22 42.6881 22 31.0581C22 30.514 22.0206 29.9747 22.0612 29.441L22.1136 29.4515C23.7428 29.7773 25.3777 30.0646 27.017 30.3135ZM52.4613 18.0397C49.8183 16.1273 46.5698 15 43.0581 15C39.54 15 36.2862 16.1313 33.6406 18.05C31.4938 17.834 29.3526 17.5435 27.221 17.1786C31.0806 12.7781 36.7449 10 43.0581 10C49.3629 10 55.0207 12.7708 58.8799 17.1612C56.7487 17.5285 54.6078 17.8214 52.4613 18.0397ZM68.9854 28.4316C69.0719 29.2954 69.1161 30.1716 69.1161 31.0581C69.1161 45.4495 57.4495 57.1161 43.0581 57.1161C28.6666 57.1161 17 45.4495 17 31.0581C17 30.1793 17.0435 29.3108 17.1284 28.4544L12.2051 27.4697C12.0696 28.6471 12 29.8444 12 31.0581C12 48.211 25.9052 62.1161 43.0581 62.1161C60.211 62.1161 74.1161 48.211 74.1161 31.0581C74.1161 29.8366 74.0456 28.6317 73.9085 27.447L68.9854 28.4316ZM69.6705 15.0372L64.3929 16.0927C59.6785 9.38418 51.8803 5 43.0581 5C34.2269 5 26.4218 9.39306 21.7089 16.1131L16.4331 15.0579C21.867 6.03506 31.7578 0 43.0581 0C54.3497 0 64.234 6.02581 69.6705 15.0372Z"
fill="var(--primary-color)"
/>
<mask id="path-2-inside-1" fill="var(--primary-color)">
<path d="M42.5 28.9252C16.5458 30.2312 0 14 0 14C0 14 26 22.9738 42.5 22.9738C59 22.9738 85 14 85 14C85 14 68.4542 27.6193 42.5 28.9252Z" />
</mask>
<path
d="M0 14L5.87269 -3.01504L-12.6052 26.8495L0 14ZM42.5 28.9252L41.5954 10.948L42.5 28.9252ZM85 14L96.4394 27.8975L79.1273 -3.01504L85 14ZM0 14C-12.6052 26.8495 -12.5999 26.8546 -12.5946 26.8598C-12.5928 26.8617 -12.5874 26.8669 -12.5837 26.8706C-12.5762 26.8779 -12.5685 26.8854 -12.5605 26.8932C-12.5445 26.9088 -12.5274 26.9254 -12.5092 26.943C-12.4729 26.9782 -12.4321 27.0174 -12.387 27.0605C-12.2969 27.1467 -12.1892 27.2484 -12.0642 27.3646C-11.8144 27.5968 -11.4949 27.8874 -11.1073 28.2273C-10.3332 28.9063 -9.28165 29.7873 -7.96614 30.7967C-5.34553 32.8073 -1.61454 35.3754 3.11693 37.872C12.5592 42.8544 26.4009 47.7581 43.4046 46.9025L41.5954 10.948C32.6449 11.3983 25.2366 8.83942 19.9174 6.03267C17.2682 4.63475 15.2406 3.22667 13.9478 2.23478C13.3066 1.74283 12.8627 1.366 12.6306 1.16243C12.5151 1.06107 12.4538 1.00422 12.4485 0.999363C12.446 0.996981 12.4576 1.00773 12.4836 1.03256C12.4966 1.04498 12.5132 1.06094 12.5334 1.08055C12.5436 1.09035 12.5546 1.10108 12.5665 1.11273C12.5725 1.11855 12.5787 1.12461 12.5852 1.13091C12.5884 1.13405 12.5934 1.13895 12.595 1.14052C12.6 1.14548 12.6052 1.15049 0 14ZM43.4046 46.9025C59.3275 46.1013 72.3155 41.5302 81.3171 37.1785C85.8337 34.9951 89.4176 32.8333 91.9552 31.151C93.2269 30.3079 94.2446 29.5794 94.9945 29.0205C95.3698 28.7409 95.6788 28.503 95.92 28.3138C96.0406 28.2192 96.1443 28.1366 96.2309 28.067C96.2742 28.0321 96.3133 28.0005 96.348 27.9723C96.3654 27.9581 96.3817 27.9448 96.3969 27.9323C96.4045 27.9261 96.4119 27.9201 96.419 27.9143C96.4225 27.9114 96.4276 27.9072 96.4294 27.9057C96.4344 27.9016 96.4394 27.8975 85 14C73.5606 0.102497 73.5655 0.0985097 73.5703 0.0945756C73.5718 0.0933319 73.5765 0.0894438 73.5795 0.0869551C73.5856 0.0819751 73.5914 0.077195 73.597 0.0726136C73.6082 0.0634509 73.6185 0.055082 73.6278 0.0474955C73.6465 0.0323231 73.6614 0.0202757 73.6726 0.0112606C73.695 -0.00676378 73.7026 -0.0126931 73.6957 -0.00726687C73.6818 0.00363418 73.6101 0.0596753 73.4822 0.154983C73.2258 0.346025 72.7482 0.691717 72.0631 1.14588C70.6873 2.05798 68.5127 3.38259 65.6485 4.7672C59.8887 7.55166 51.6267 10.4432 41.5954 10.948L43.4046 46.9025ZM85 14C79.1273 -3.01504 79.1288 -3.01557 79.1303 -3.01606C79.1306 -3.01618 79.1319 -3.01664 79.1326 -3.01688C79.134 -3.01736 79.135 -3.0177 79.1356 -3.01791C79.1369 -3.01834 79.1366 -3.01823 79.1347 -3.01759C79.131 -3.01633 79.1212 -3.01297 79.1055 -3.00758C79.0739 -2.99681 79.0185 -2.97794 78.9404 -2.95151C78.7839 -2.89864 78.5366 -2.81564 78.207 -2.7068C77.5472 -2.48895 76.561 -2.16874 75.3165 -1.78027C72.8181 -1.00046 69.3266 0.039393 65.3753 1.07466C57.0052 3.26771 48.2826 4.97383 42.5 4.97383V40.9738C53.2174 40.9738 65.7448 38.193 74.4997 35.8992C79.1109 34.691 83.1506 33.4874 86.0429 32.5846C87.4937 32.1318 88.6676 31.7509 89.4942 31.478C89.9077 31.3414 90.2351 31.2317 90.4676 31.1531C90.5839 31.1138 90.6765 31.0823 90.7443 31.0591C90.7783 31.0475 90.806 31.038 90.8275 31.0306C90.8382 31.0269 90.8473 31.0238 90.8549 31.0212C90.8586 31.0199 90.862 31.0187 90.865 31.0177C90.8665 31.0172 90.8684 31.0165 90.8691 31.0163C90.871 31.0156 90.8727 31.015 85 14ZM42.5 4.97383C36.7174 4.97383 27.9948 3.26771 19.6247 1.07466C15.6734 0.039393 12.1819 -1.00046 9.68352 -1.78027C8.43897 -2.16874 7.4528 -2.48895 6.79299 -2.7068C6.46337 -2.81564 6.21607 -2.89864 6.05965 -2.95151C5.98146 -2.97794 5.92606 -2.99681 5.89453 -3.00758C5.87876 -3.01297 5.86897 -3.01633 5.86528 -3.01759C5.86344 -3.01823 5.86312 -3.01834 5.86435 -3.01791C5.86497 -3.0177 5.86597 -3.01736 5.86736 -3.01688C5.86805 -3.01664 5.86939 -3.01618 5.86973 -3.01606C5.87116 -3.01557 5.87269 -3.01504 0 14C-5.87269 31.015 -5.87096 31.0156 -5.86914 31.0163C-5.8684 31.0165 -5.86647 31.0172 -5.86498 31.0177C-5.86201 31.0187 -5.85864 31.0199 -5.85486 31.0212C-5.84732 31.0238 -5.83818 31.0269 -5.82747 31.0306C-5.80603 31.038 -5.77828 31.0475 -5.74435 31.0591C-5.67649 31.0823 -5.58388 31.1138 -5.46761 31.1531C-5.23512 31.2317 -4.9077 31.3414 -4.49416 31.478C-3.66764 31.7509 -2.49366 32.1318 -1.04289 32.5846C1.84938 33.4874 5.88908 34.691 10.5003 35.8992C19.2552 38.193 31.7826 40.9738 42.5 40.9738V4.97383Z"
fill="var(--primary-color)"
mask="url(#path-2-inside-1)"
/>
</svg>
<span>APOLLO</span>
</router-link>
</div>
<button class="layout-menu-button layout-topbar-action" @click="onMenuToggle">
<i class="pi pi-bars"></i>
</button>
<div class="layout-topbar-actions">
<div class="layout-config-menu">
<button type="button" class="layout-topbar-action" @click="toggleDarkMode">
<i :class="['pi', { 'pi-moon': isDarkTheme, 'pi-sun': !isDarkTheme }]"></i>
</button>
<div class="relative">
<button
v-styleclass="{ selector: '@next', enterFromClass: 'hidden', enterActiveClass: 'animate-scalein', leaveToClass: 'hidden', leaveActiveClass: 'animate-fadeout', hideOnOutsideClick: true }"
type="button"
class="layout-topbar-action layout-topbar-action-highlight"
>
<i class="pi pi-palette"></i>
</button>
<AppConfigurator />
</div>
</div>
<button
class="layout-topbar-menu-button layout-topbar-action"
v-styleclass="{ selector: '@next', enterFromClass: 'hidden', enterActiveClass: 'animate-scalein', leaveToClass: 'hidden', leaveActiveClass: 'animate-fadeout', hideOnOutsideClick: true }"
>
<i class="pi pi-ellipsis-v"></i>
</button>
<div class="layout-topbar-menu hidden lg:block">
<div class="layout-topbar-menu-content">
<button type="button" class="layout-topbar-action">
<i class="pi pi-calendar"></i>
<span>Calendar</span>
</button>
<button type="button" class="layout-topbar-action">
<i class="pi pi-inbox"></i>
<span>Messages</span>
</button>
<button type="button" class="layout-topbar-action">
<i class="pi pi-user"></i>
<span>Profile</span>
</button>
</div>
</div>
</div>
</div>
</template>

View File

@@ -0,0 +1,78 @@
import { computed, reactive, readonly } from 'vue';
const layoutConfig = reactive({
preset: 'Aura',
primary: 'emerald',
surface: null,
darkTheme: false,
menuMode: 'static',
activeMenuItem: null
});
const layoutState = reactive({
staticMenuDesktopInactive: false,
overlayMenuActive: false,
profileSidebarVisible: false,
configSidebarVisible: false,
staticMenuMobileActive: false,
menuHoverActive: false
});
export function useLayout() {
const setPrimary = (value) => {
layoutConfig.primary = value;
};
const setSurface = (value) => {
layoutConfig.surface = value;
};
const setPreset = (value) => {
layoutConfig.preset = value;
};
const setActiveMenuItem = (item) => {
layoutConfig.activeMenuItem = item.value || item;
};
const toggleDarkMode = () => {
if (!document.startViewTransition) {
executeDarkModeToggle();
return;
}
document.startViewTransition(() => executeDarkModeToggle(event));
};
const executeDarkModeToggle = () => {
layoutConfig.darkTheme = !layoutConfig.darkTheme;
document.documentElement.classList.toggle('app-dark');
};
const onMenuToggle = () => {
if (layoutConfig.menuMode === 'overlay') {
layoutState.overlayMenuActive = !layoutState.overlayMenuActive;
}
if (window.innerWidth > 991) {
layoutState.staticMenuDesktopInactive = !layoutState.staticMenuDesktopInactive;
} else {
layoutState.staticMenuMobileActive = !layoutState.staticMenuMobileActive;
}
};
const resetMenu = () => {
layoutState.overlayMenuActive = false;
layoutState.staticMenuMobileActive = false;
layoutState.menuHoverActive = false;
};
const isSidebarActive = computed(() => layoutState.overlayMenuActive || layoutState.staticMenuMobileActive);
const isDarkTheme = computed(() => layoutConfig.darkTheme);
const getPrimary = computed(() => layoutConfig.primary);
return { layoutConfig: readonly(layoutConfig), layoutState: readonly(layoutState), onMenuToggle, isSidebarActive, isDarkTheme, getPrimary, setActiveMenuItem, toggleDarkMode, setPrimary, setSurface, setPreset, resetMenu };
}

31
src/main.js Normal file
View File

@@ -0,0 +1,31 @@
import { createApp } from 'vue';
import App from './App.vue';
import router from './router';
import PrimeVue from 'primevue/config';
import Aura from '@primevue/themes/aura';
import ToastService from 'primevue/toastservice';
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, {
theme: {
preset: Aura,
options: {
darkModeSelector: '.app-dark'
}
}
});
app.use(ToastService);
app.use(ConfirmationService);
app.component('BlockViewer', BlockViewer);
app.mount('#app');

31
src/router/index.js Normal file
View File

@@ -0,0 +1,31 @@
import AppLayout from '@/layout/AppLayout.vue';
import { createRouter, createWebHistory } from 'vue-router';
const router = createRouter({
history: createWebHistory(),
routes: [
{
path: '/',
component: AppLayout,
children: [
{
path: '/',
name: 'dashboard',
component: () => import('@/views/Dashboard.vue')
},
{
path: '/ksdocuments',
children: [
{path: '', name: 'ks-document', component: () => import('@/views/pages/KsDocuments.vue')},
{path: 'new', name: 'ks-document-new', component: () => import('@/views/pages/KsDocumentForm.vue')},
{path: ':id', name: 'ks-document-edit', component: () => import('@/views/pages/KsDocumentForm.vue')}
]
},
]
}
]
});
export default router;

View File

@@ -0,0 +1,252 @@
export const CountryService = {
getData() {
return [
{ name: 'Afghanistan', code: 'AF' },
{ name: 'Albania', code: 'AL' },
{ name: 'Algeria', code: 'DZ' },
{ name: 'American Samoa', code: 'AS' },
{ name: 'Andorra', code: 'AD' },
{ name: 'Angola', code: 'AO' },
{ name: 'Anguilla', code: 'AI' },
{ name: 'Antarctica', code: 'AQ' },
{ name: 'Antigua and Barbuda', code: 'AG' },
{ name: 'Argentina', code: 'AR' },
{ name: 'Armenia', code: 'AM' },
{ name: 'Aruba', code: 'AW' },
{ name: 'Australia', code: 'AU' },
{ name: 'Austria', code: 'AT' },
{ name: 'Azerbaijan', code: 'AZ' },
{ name: 'Bahamas', code: 'BS' },
{ name: 'Bahrain', code: 'BH' },
{ name: 'Bangladesh', code: 'BD' },
{ name: 'Barbados', code: 'BB' },
{ name: 'Belarus', code: 'BY' },
{ name: 'Belgium', code: 'BE' },
{ name: 'Belize', code: 'BZ' },
{ name: 'Benin', code: 'BJ' },
{ name: 'Bermuda', code: 'BM' },
{ name: 'Bhutan', code: 'BT' },
{ name: 'Bolivia', code: 'BO' },
{ name: 'Bosnia and Herzegovina', code: 'BA' },
{ name: 'Botswana', code: 'BW' },
{ name: 'Bouvet Island', code: 'BV' },
{ name: 'Brazil', code: 'BR' },
{ name: 'British Indian Ocean Territory', code: 'IO' },
{ name: 'Brunei Darussalam', code: 'BN' },
{ name: 'Bulgaria', code: 'BG' },
{ name: 'Burkina Faso', code: 'BF' },
{ name: 'Burundi', code: 'BI' },
{ name: 'Cambodia', code: 'KH' },
{ name: 'Cameroon', code: 'CM' },
{ name: 'Canada', code: 'CA' },
{ name: 'Cape Verde', code: 'CV' },
{ name: 'Cayman Islands', code: 'KY' },
{ name: 'Central African Republic', code: 'CF' },
{ name: 'Chad', code: 'TD' },
{ name: 'Chile', code: 'CL' },
{ name: 'China', code: 'CN' },
{ name: 'Christmas Island', code: 'CX' },
{ name: 'Cocos (Keeling) Islands', code: 'CC' },
{ name: 'Colombia', code: 'CO' },
{ name: 'Comoros', code: 'KM' },
{ name: 'Congo', code: 'CG' },
{ name: 'Congo, The Democratic Republic of the', code: 'CD' },
{ name: 'Cook Islands', code: 'CK' },
{ name: 'Costa Rica', code: 'CR' },
{ name: 'Cote D"Ivoire', code: 'CI' },
{ name: 'Croatia', code: 'HR' },
{ name: 'Cuba', code: 'CU' },
{ name: 'Cyprus', code: 'CY' },
{ name: 'Czech Republic', code: 'CZ' },
{ name: 'Denmark', code: 'DK' },
{ name: 'Djibouti', code: 'DJ' },
{ name: 'Dominica', code: 'DM' },
{ name: 'Dominican Republic', code: 'DO' },
{ name: 'Ecuador', code: 'EC' },
{ name: 'Egypt', code: 'EG' },
{ name: 'El Salvador', code: 'SV' },
{ name: 'Equatorial Guinea', code: 'GQ' },
{ name: 'Eritrea', code: 'ER' },
{ name: 'Estonia', code: 'EE' },
{ name: 'Ethiopia', code: 'ET' },
{ name: 'Falkland Islands (Malvinas)', code: 'FK' },
{ name: 'Faroe Islands', code: 'FO' },
{ name: 'Fiji', code: 'FJ' },
{ name: 'Finland', code: 'FI' },
{ name: 'France', code: 'FR' },
{ name: 'French Guiana', code: 'GF' },
{ name: 'French Polynesia', code: 'PF' },
{ name: 'French Southern Territories', code: 'TF' },
{ name: 'Gabon', code: 'GA' },
{ name: 'Gambia', code: 'GM' },
{ name: 'Georgia', code: 'GE' },
{ name: 'Germany', code: 'DE' },
{ name: 'Ghana', code: 'GH' },
{ name: 'Gibraltar', code: 'GI' },
{ name: 'Greece', code: 'GR' },
{ name: 'Greenland', code: 'GL' },
{ name: 'Grenada', code: 'GD' },
{ name: 'Guadeloupe', code: 'GP' },
{ name: 'Guam', code: 'GU' },
{ name: 'Guatemala', code: 'GT' },
{ name: 'Guernsey', code: 'GG' },
{ name: 'Guinea', code: 'GN' },
{ name: 'Guinea-Bissau', code: 'GW' },
{ name: 'Guyana', code: 'GY' },
{ name: 'Haiti', code: 'HT' },
{ name: 'Heard Island and Mcdonald Islands', code: 'HM' },
{ name: 'Holy See (Vatican City State)', code: 'VA' },
{ name: 'Honduras', code: 'HN' },
{ name: 'Hong Kong', code: 'HK' },
{ name: 'Hungary', code: 'HU' },
{ name: 'Iceland', code: 'IS' },
{ name: 'India', code: 'IN' },
{ name: 'Indonesia', code: 'ID' },
{ name: 'Iran, Islamic Republic Of', code: 'IR' },
{ name: 'Iraq', code: 'IQ' },
{ name: 'Ireland', code: 'IE' },
{ name: 'Isle of Man', code: 'IM' },
{ name: 'Israel', code: 'IL' },
{ name: 'Italy', code: 'IT' },
{ name: 'Jamaica', code: 'JM' },
{ name: 'Japan', code: 'JP' },
{ name: 'Jersey', code: 'JE' },
{ name: 'Jordan', code: 'JO' },
{ name: 'Kazakhstan', code: 'KZ' },
{ name: 'Kenya', code: 'KE' },
{ name: 'Kiribati', code: 'KI' },
{ name: 'Korea, Democratic People"S Republic of', code: 'KP' },
{ name: 'Korea, Republic of', code: 'KR' },
{ name: 'Kuwait', code: 'KW' },
{ name: 'Kyrgyzstan', code: 'KG' },
{ name: 'Lao People"S Democratic Republic', code: 'LA' },
{ name: 'Latvia', code: 'LV' },
{ name: 'Lebanon', code: 'LB' },
{ name: 'Lesotho', code: 'LS' },
{ name: 'Liberia', code: 'LR' },
{ name: 'Libyan Arab Jamahiriya', code: 'LY' },
{ name: 'Liechtenstein', code: 'LI' },
{ name: 'Lithuania', code: 'LT' },
{ name: 'Luxembourg', code: 'LU' },
{ name: 'Macao', code: 'MO' },
{ name: 'Macedonia, The Former Yugoslav Republic of', code: 'MK' },
{ name: 'Madagascar', code: 'MG' },
{ name: 'Malawi', code: 'MW' },
{ name: 'Malaysia', code: 'MY' },
{ name: 'Maldives', code: 'MV' },
{ name: 'Mali', code: 'ML' },
{ name: 'Malta', code: 'MT' },
{ name: 'Marshall Islands', code: 'MH' },
{ name: 'Martinique', code: 'MQ' },
{ name: 'Mauritania', code: 'MR' },
{ name: 'Mauritius', code: 'MU' },
{ name: 'Mayotte', code: 'YT' },
{ name: 'Mexico', code: 'MX' },
{ name: 'Micronesia, Federated States of', code: 'FM' },
{ name: 'Moldova, Republic of', code: 'MD' },
{ name: 'Monaco', code: 'MC' },
{ name: 'Mongolia', code: 'MN' },
{ name: 'Montserrat', code: 'MS' },
{ name: 'Morocco', code: 'MA' },
{ name: 'Mozambique', code: 'MZ' },
{ name: 'Myanmar', code: 'MM' },
{ name: 'Namibia', code: 'NA' },
{ name: 'Nauru', code: 'NR' },
{ name: 'Nepal', code: 'NP' },
{ name: 'Netherlands', code: 'NL' },
{ name: 'Netherlands Antilles', code: 'AN' },
{ name: 'New Caledonia', code: 'NC' },
{ name: 'New Zealand', code: 'NZ' },
{ name: 'Nicaragua', code: 'NI' },
{ name: 'Niger', code: 'NE' },
{ name: 'Nigeria', code: 'NG' },
{ name: 'Niue', code: 'NU' },
{ name: 'Norfolk Island', code: 'NF' },
{ name: 'Northern Mariana Islands', code: 'MP' },
{ name: 'Norway', code: 'NO' },
{ name: 'Oman', code: 'OM' },
{ name: 'Pakistan', code: 'PK' },
{ name: 'Palau', code: 'PW' },
{ name: 'Palestinian Territory, Occupied', code: 'PS' },
{ name: 'Panama', code: 'PA' },
{ name: 'Papua New Guinea', code: 'PG' },
{ name: 'Paraguay', code: 'PY' },
{ name: 'Peru', code: 'PE' },
{ name: 'Philippines', code: 'PH' },
{ name: 'Pitcairn', code: 'PN' },
{ name: 'Poland', code: 'PL' },
{ name: 'Portugal', code: 'PT' },
{ name: 'Puerto Rico', code: 'PR' },
{ name: 'Qatar', code: 'QA' },
{ name: 'Reunion', code: 'RE' },
{ name: 'Romania', code: 'RO' },
{ name: 'Russian Federation', code: 'RU' },
{ name: 'RWANDA', code: 'RW' },
{ name: 'Saint Helena', code: 'SH' },
{ name: 'Saint Kitts and Nevis', code: 'KN' },
{ name: 'Saint Lucia', code: 'LC' },
{ name: 'Saint Pierre and Miquelon', code: 'PM' },
{ name: 'Saint Vincent and the Grenadines', code: 'VC' },
{ name: 'Samoa', code: 'WS' },
{ name: 'San Marino', code: 'SM' },
{ name: 'Sao Tome and Principe', code: 'ST' },
{ name: 'Saudi Arabia', code: 'SA' },
{ name: 'Senegal', code: 'SN' },
{ name: 'Serbia and Montenegro', code: 'CS' },
{ name: 'Seychelles', code: 'SC' },
{ name: 'Sierra Leone', code: 'SL' },
{ name: 'Singapore', code: 'SG' },
{ name: 'Slovakia', code: 'SK' },
{ name: 'Slovenia', code: 'SI' },
{ name: 'Solomon Islands', code: 'SB' },
{ name: 'Somalia', code: 'SO' },
{ name: 'South Africa', code: 'ZA' },
{ name: 'South Georgia and the South Sandwich Islands', code: 'GS' },
{ name: 'Spain', code: 'ES' },
{ name: 'Sri Lanka', code: 'LK' },
{ name: 'Sudan', code: 'SD' },
{ name: 'Suriname', code: 'SR' },
{ name: 'Svalbard and Jan Mayen', code: 'SJ' },
{ name: 'Swaziland', code: 'SZ' },
{ name: 'Sweden', code: 'SE' },
{ name: 'Switzerland', code: 'CH' },
{ name: 'Syrian Arab Republic', code: 'SY' },
{ name: 'Taiwan, Province of China', code: 'TW' },
{ name: 'Tajikistan', code: 'TJ' },
{ name: 'Tanzania, United Republic of', code: 'TZ' },
{ name: 'Thailand', code: 'TH' },
{ name: 'Timor-Leste', code: 'TL' },
{ name: 'Togo', code: 'TG' },
{ name: 'Tokelau', code: 'TK' },
{ name: 'Tonga', code: 'TO' },
{ name: 'Trinidad and Tobago', code: 'TT' },
{ name: 'Tunisia', code: 'TN' },
{ name: 'Turkey', code: 'TR' },
{ name: 'Turkmenistan', code: 'TM' },
{ name: 'Turks and Caicos Islands', code: 'TC' },
{ name: 'Tuvalu', code: 'TV' },
{ name: 'Uganda', code: 'UG' },
{ name: 'Ukraine', code: 'UA' },
{ name: 'United Arab Emirates', code: 'AE' },
{ name: 'United Kingdom', code: 'GB' },
{ name: 'United States', code: 'US' },
{ name: 'United States Minor Outlying Islands', code: 'UM' },
{ name: 'Uruguay', code: 'UY' },
{ name: 'Uzbekistan', code: 'UZ' },
{ name: 'Vanuatu', code: 'VU' },
{ name: 'Venezuela', code: 'VE' },
{ name: 'Viet Nam', code: 'VN' },
{ name: 'Virgin Islands, British', code: 'VG' },
{ name: 'Virgin Islands, U.S.', code: 'VI' },
{ name: 'Wallis and Futuna', code: 'WF' },
{ name: 'Western Sahara', code: 'EH' },
{ name: 'Yemen', code: 'YE' },
{ name: 'Zambia', code: 'ZM' },
{ name: 'Zimbabwe', code: 'ZW' }
];
},
getCountries() {
return Promise.resolve(this.getData());
}
};

File diff suppressed because it is too large Load Diff

431
src/service/NodeService.js Normal file
View File

@@ -0,0 +1,431 @@
export const NodeService = {
getTreeNodesData() {
return [
{
key: '0',
label: 'Documents',
data: 'Documents Folder',
icon: 'pi pi-fw pi-inbox',
children: [
{
key: '0-0',
label: 'Work',
data: 'Work Folder',
icon: 'pi pi-fw pi-cog',
children: [
{ key: '0-0-0', label: 'Expenses.doc', icon: 'pi pi-fw pi-file', data: 'Expenses Document' },
{ key: '0-0-1', label: 'Resume.doc', icon: 'pi pi-fw pi-file', data: 'Resume Document' }
]
},
{
key: '0-1',
label: 'Home',
data: 'Home Folder',
icon: 'pi pi-fw pi-home',
children: [{ key: '0-1-0', label: 'Invoices.txt', icon: 'pi pi-fw pi-file', data: 'Invoices for this month' }]
}
]
},
{
key: '1',
label: 'Events',
data: 'Events Folder',
icon: 'pi pi-fw pi-calendar',
children: [
{ key: '1-0', label: 'Meeting', icon: 'pi pi-fw pi-calendar-plus', data: 'Meeting' },
{ key: '1-1', label: 'Product Launch', icon: 'pi pi-fw pi-calendar-plus', data: 'Product Launch' },
{ key: '1-2', label: 'Report Review', icon: 'pi pi-fw pi-calendar-plus', data: 'Report Review' }
]
},
{
key: '2',
label: 'Movies',
data: 'Movies Folder',
icon: 'pi pi-fw pi-star-fill',
children: [
{
key: '2-0',
icon: 'pi pi-fw pi-star-fill',
label: 'Al Pacino',
data: 'Pacino Movies',
children: [
{ key: '2-0-0', label: 'Scarface', icon: 'pi pi-fw pi-video', data: 'Scarface Movie' },
{ key: '2-0-1', label: 'Serpico', icon: 'pi pi-fw pi-video', data: 'Serpico Movie' }
]
},
{
key: '2-1',
label: 'Robert De Niro',
icon: 'pi pi-fw pi-star-fill',
data: 'De Niro Movies',
children: [
{ key: '2-1-0', label: 'Goodfellas', icon: 'pi pi-fw pi-video', data: 'Goodfellas Movie' },
{ key: '2-1-1', label: 'Untouchables', icon: 'pi pi-fw pi-video', data: 'Untouchables Movie' }
]
}
]
}
];
},
getTreeTableNodesData() {
return [
{
key: '0',
data: {
name: 'Applications',
size: '100kb',
type: 'Folder'
},
children: [
{
key: '0-0',
data: {
name: 'Vue',
size: '25kb',
type: 'Folder'
},
children: [
{
key: '0-0-0',
data: {
name: 'vue.app',
size: '10kb',
type: 'Application'
}
},
{
key: '0-0-1',
data: {
name: 'native.app',
size: '10kb',
type: 'Application'
}
},
{
key: '0-0-2',
data: {
name: 'mobile.app',
size: '5kb',
type: 'Application'
}
}
]
},
{
key: '0-1',
data: {
name: 'editor.app',
size: '25kb',
type: 'Application'
}
},
{
key: '0-2',
data: {
name: 'settings.app',
size: '50kb',
type: 'Application'
}
}
]
},
{
key: '1',
data: {
name: 'Cloud',
size: '20kb',
type: 'Folder'
},
children: [
{
key: '1-0',
data: {
name: 'backup-1.zip',
size: '10kb',
type: 'Zip'
}
},
{
key: '1-1',
data: {
name: 'backup-2.zip',
size: '10kb',
type: 'Zip'
}
}
]
},
{
key: '2',
data: {
name: 'Desktop',
size: '150kb',
type: 'Folder'
},
children: [
{
key: '2-0',
data: {
name: 'note-meeting.txt',
size: '50kb',
type: 'Text'
}
},
{
key: '2-1',
data: {
name: 'note-todo.txt',
size: '100kb',
type: 'Text'
}
}
]
},
{
key: '3',
data: {
name: 'Documents',
size: '75kb',
type: 'Folder'
},
children: [
{
key: '3-0',
data: {
name: 'Work',
size: '55kb',
type: 'Folder'
},
children: [
{
key: '3-0-0',
data: {
name: 'Expenses.doc',
size: '30kb',
type: 'Document'
}
},
{
key: '3-0-1',
data: {
name: 'Resume.doc',
size: '25kb',
type: 'Resume'
}
}
]
},
{
key: '3-1',
data: {
name: 'Home',
size: '20kb',
type: 'Folder'
},
children: [
{
key: '3-1-0',
data: {
name: 'Invoices',
size: '20kb',
type: 'Text'
}
}
]
}
]
},
{
key: '4',
data: {
name: 'Downloads',
size: '25kb',
type: 'Folder'
},
children: [
{
key: '4-0',
data: {
name: 'Spanish',
size: '10kb',
type: 'Folder'
},
children: [
{
key: '4-0-0',
data: {
name: 'tutorial-a1.txt',
size: '5kb',
type: 'Text'
}
},
{
key: '4-0-1',
data: {
name: 'tutorial-a2.txt',
size: '5kb',
type: 'Text'
}
}
]
},
{
key: '4-1',
data: {
name: 'Travel',
size: '15kb',
type: 'Text'
},
children: [
{
key: '4-1-0',
data: {
name: 'Hotel.pdf',
size: '10kb',
type: 'PDF'
}
},
{
key: '4-1-1',
data: {
name: 'Flight.pdf',
size: '5kb',
type: 'PDF'
}
}
]
}
]
},
{
key: '5',
data: {
name: 'Main',
size: '50kb',
type: 'Folder'
},
children: [
{
key: '5-0',
data: {
name: 'bin',
size: '50kb',
type: 'Link'
}
},
{
key: '5-1',
data: {
name: 'etc',
size: '100kb',
type: 'Link'
}
},
{
key: '5-2',
data: {
name: 'var',
size: '100kb',
type: 'Link'
}
}
]
},
{
key: '6',
data: {
name: 'Other',
size: '5kb',
type: 'Folder'
},
children: [
{
key: '6-0',
data: {
name: 'todo.txt',
size: '3kb',
type: 'Text'
}
},
{
key: '6-1',
data: {
name: 'logo.png',
size: '2kb',
type: 'Picture'
}
}
]
},
{
key: '7',
data: {
name: 'Pictures',
size: '150kb',
type: 'Folder'
},
children: [
{
key: '7-0',
data: {
name: 'barcelona.jpg',
size: '90kb',
type: 'Picture'
}
},
{
key: '7-1',
data: {
name: 'primevue.png',
size: '30kb',
type: 'Picture'
}
},
{
key: '7-2',
data: {
name: 'prime.jpg',
size: '30kb',
type: 'Picture'
}
}
]
},
{
key: '8',
data: {
name: 'Videos',
size: '1500kb',
type: 'Folder'
},
children: [
{
key: '8-0',
data: {
name: 'primefaces.mkv',
size: '1000kb',
type: 'Video'
}
},
{
key: '8-1',
data: {
name: 'intro.avi',
size: '500kb',
type: 'Video'
}
}
]
}
];
},
getTreeTableNodes() {
return Promise.resolve(this.getTreeTableNodesData());
},
getTreeNodes() {
return Promise.resolve(this.getTreeNodesData());
}
};

100
src/service/PhotoService.js Normal file
View File

@@ -0,0 +1,100 @@
export const PhotoService = {
getData() {
return [
{
itemImageSrc: 'https://primefaces.org/cdn/primevue/images/galleria/galleria1.jpg',
thumbnailImageSrc: 'https://primefaces.org/cdn/primevue/images/galleria/galleria1s.jpg',
alt: 'Description for Image 1',
title: 'Title 1'
},
{
itemImageSrc: 'https://primefaces.org/cdn/primevue/images/galleria/galleria2.jpg',
thumbnailImageSrc: 'https://primefaces.org/cdn/primevue/images/galleria/galleria2s.jpg',
alt: 'Description for Image 2',
title: 'Title 2'
},
{
itemImageSrc: 'https://primefaces.org/cdn/primevue/images/galleria/galleria3.jpg',
thumbnailImageSrc: 'https://primefaces.org/cdn/primevue/images/galleria/galleria3s.jpg',
alt: 'Description for Image 3',
title: 'Title 3'
},
{
itemImageSrc: 'https://primefaces.org/cdn/primevue/images/galleria/galleria4.jpg',
thumbnailImageSrc: 'https://primefaces.org/cdn/primevue/images/galleria/galleria4s.jpg',
alt: 'Description for Image 4',
title: 'Title 4'
},
{
itemImageSrc: 'https://primefaces.org/cdn/primevue/images/galleria/galleria5.jpg',
thumbnailImageSrc: 'https://primefaces.org/cdn/primevue/images/galleria/galleria5s.jpg',
alt: 'Description for Image 5',
title: 'Title 5'
},
{
itemImageSrc: 'https://primefaces.org/cdn/primevue/images/galleria/galleria6.jpg',
thumbnailImageSrc: 'https://primefaces.org/cdn/primevue/images/galleria/galleria6s.jpg',
alt: 'Description for Image 6',
title: 'Title 6'
},
{
itemImageSrc: 'https://primefaces.org/cdn/primevue/images/galleria/galleria7.jpg',
thumbnailImageSrc: 'https://primefaces.org/cdn/primevue/images/galleria/galleria7s.jpg',
alt: 'Description for Image 7',
title: 'Title 7'
},
{
itemImageSrc: 'https://primefaces.org/cdn/primevue/images/galleria/galleria8.jpg',
thumbnailImageSrc: 'https://primefaces.org/cdn/primevue/images/galleria/galleria8s.jpg',
alt: 'Description for Image 8',
title: 'Title 8'
},
{
itemImageSrc: 'https://primefaces.org/cdn/primevue/images/galleria/galleria9.jpg',
thumbnailImageSrc: 'https://primefaces.org/cdn/primevue/images/galleria/galleria9s.jpg',
alt: 'Description for Image 9',
title: 'Title 9'
},
{
itemImageSrc: 'https://primefaces.org/cdn/primevue/images/galleria/galleria10.jpg',
thumbnailImageSrc: 'https://primefaces.org/cdn/primevue/images/galleria/galleria10s.jpg',
alt: 'Description for Image 10',
title: 'Title 10'
},
{
itemImageSrc: 'https://primefaces.org/cdn/primevue/images/galleria/galleria11.jpg',
thumbnailImageSrc: 'https://primefaces.org/cdn/primevue/images/galleria/galleria11s.jpg',
alt: 'Description for Image 11',
title: 'Title 11'
},
{
itemImageSrc: 'https://primefaces.org/cdn/primevue/images/galleria/galleria12.jpg',
thumbnailImageSrc: 'https://primefaces.org/cdn/primevue/images/galleria/galleria12s.jpg',
alt: 'Description for Image 12',
title: 'Title 12'
},
{
itemImageSrc: 'https://primefaces.org/cdn/primevue/images/galleria/galleria13.jpg',
thumbnailImageSrc: 'https://primefaces.org/cdn/primevue/images/galleria/galleria13s.jpg',
alt: 'Description for Image 13',
title: 'Title 13'
},
{
itemImageSrc: 'https://primefaces.org/cdn/primevue/images/galleria/galleria14.jpg',
thumbnailImageSrc: 'https://primefaces.org/cdn/primevue/images/galleria/galleria14s.jpg',
alt: 'Description for Image 14',
title: 'Title 14'
},
{
itemImageSrc: 'https://primefaces.org/cdn/primevue/images/galleria/galleria15.jpg',
thumbnailImageSrc: 'https://primefaces.org/cdn/primevue/images/galleria/galleria15s.jpg',
alt: 'Description for Image 15',
title: 'Title 15'
}
];
},
getImages() {
return Promise.resolve(this.getData());
}
};

File diff suppressed because it is too large Load Diff

334
src/views/Dashboard.vue Normal file
View File

@@ -0,0 +1,334 @@
<script setup>
import { useLayout } from '@/layout/composables/layout';
import { ProductService } from '@/service/ProductService';
import { onMounted, ref, watch } from 'vue';
const { getPrimary, isDarkTheme } = useLayout();
const products = ref(null);
const chartData = ref(null);
const chartOptions = ref(null);
const items = ref([
{ label: 'Add New', icon: 'pi pi-fw pi-plus' },
{ label: 'Remove', icon: 'pi pi-fw pi-minus' }
]);
onMounted(() => {
ProductService.getProductsSmall().then((data) => (products.value = data));
chartData.value = setChartData();
chartOptions.value = setChartOptions();
});
function setChartData() {
const documentStyle = getComputedStyle(document.documentElement);
return {
labels: ['Q1', 'Q2', 'Q3', 'Q4'],
datasets: [
{
type: 'bar',
label: 'Personal Wallet',
backgroundColor: 'color-mix(in srgb, ' + documentStyle.getPropertyValue('--p-primary-400') + ' 100%, #fff)',
data: [4000, 10000, 15000, 4000],
barThickness: 32
},
{
type: 'bar',
label: 'Corporate Wallet',
backgroundColor: 'color-mix(in srgb, ' + documentStyle.getPropertyValue('--p-primary-300') + ' 100%, transparent)',
data: [2100, 8400, 2400, 7500],
barThickness: 32
},
{
type: 'bar',
label: 'Investment Wallet',
backgroundColor: 'color-mix(in srgb, ' + documentStyle.getPropertyValue('--p-primary-200') + ' 100%, transparent)',
data: [4100, 5200, 3400, 7400],
borderRadius: {
topLeft: 8,
topRight: 8
},
borderSkipped: true,
barThickness: 32
}
]
};
}
function setChartOptions() {
const documentStyle = getComputedStyle(document.documentElement);
const borderColor = documentStyle.getPropertyValue('--surface-border');
const textMutedColor = documentStyle.getPropertyValue('--text-color-secondary');
return {
maintainAspectRatio: false,
aspectRatio: 0.8,
scales: {
x: {
stacked: true,
ticks: {
color: textMutedColor
},
grid: {
color: 'transparent',
borderColor: 'transparent'
}
},
y: {
stacked: true,
ticks: {
color: textMutedColor
},
grid: {
color: borderColor,
borderColor: 'transparent',
drawTicks: false
}
}
}
};
}
const formatCurrency = (value) => {
return value.toLocaleString('en-US', { style: 'currency', currency: 'USD' });
};
watch(isDarkTheme, () => {
chartData.value = setChartData();
chartOptions.value = setChartOptions();
});
watch(getPrimary, () => {
chartData.value = setChartData();
chartOptions.value = setChartOptions();
});
</script>
<template>
<div class="grid grid-cols-12 gap-8">
<div class="col-span-12 lg:col-span-6 xl:col-span-3">
<div class="card mb-0">
<div class="flex justify-between mb-4">
<div>
<span class="block text-muted-color font-medium mb-4">Orders</span>
<div class="text-surface-900 dark:text-surface-0 font-medium text-xl">152</div>
</div>
<div class="flex items-center justify-center bg-blue-100 rounded-border" style="width: 2.5rem; height: 2.5rem">
<i class="pi pi-shopping-cart text-blue-500 text-xl"></i>
</div>
</div>
<span class="text-primary font-medium">24 new </span>
<span class="text-muted-color">since last visit</span>
</div>
</div>
<div class="col-span-12 lg:col-span-6 xl:col-span-3">
<div class="card mb-0">
<div class="flex justify-between mb-4">
<div>
<span class="block text-muted-color font-medium mb-4">Revenue</span>
<div class="text-surface-900 dark:text-surface-0 font-medium text-xl">$2.100</div>
</div>
<div class="flex items-center justify-center bg-orange-100 rounded-border" style="width: 2.5rem; height: 2.5rem">
<i class="pi pi-map-marker text-orange-500 text-xl"></i>
</div>
</div>
<span class="text-primary font-medium">%52+ </span>
<span class="text-muted-color">since last week</span>
</div>
</div>
<div class="col-span-12 lg:col-span-6 xl:col-span-3">
<div class="card mb-0">
<div class="flex justify-between mb-4">
<div>
<span class="block text-muted-color font-medium mb-4">Customers</span>
<div class="text-surface-900 dark:text-surface-0 font-medium text-xl">28441</div>
</div>
<div class="flex items-center justify-center bg-cyan-100 rounded-border" style="width: 2.5rem; height: 2.5rem">
<i class="pi pi-inbox text-cyan-500 text-xl"></i>
</div>
</div>
<span class="text-primary font-medium">520 </span>
<span class="text-muted-color">newly registered</span>
</div>
</div>
<div class="col-span-12 lg:col-span-6 xl:col-span-3">
<div class="card mb-0">
<div class="flex justify-between mb-4">
<div>
<span class="block text-muted-color font-medium mb-4">Comments</span>
<div class="text-surface-900 dark:text-surface-0 font-medium text-xl">152 Unread</div>
</div>
<div class="flex items-center justify-center bg-purple-100 rounded-border" style="width: 2.5rem; height: 2.5rem">
<i class="pi pi-comment text-purple-500 text-xl"></i>
</div>
</div>
<span class="text-primary font-medium">85 </span>
<span class="text-muted-color">responded</span>
</div>
</div>
<div class="col-span-12 xl:col-span-6">
<div class="card">
<div class="font-semibold text-xl mb-4">Recent Sales</div>
<DataTable :value="products" :rows="5" :paginator="true" responsiveLayout="scroll">
<Column style="width: 15%" header="Image">
<template #body="slotProps">
<img :src="'demo/images/product/' + slotProps.data.image" :alt="slotProps.data.image" width="50" class="shadow" />
</template>
</Column>
<Column field="name" header="Name" :sortable="true" style="width: 35%"></Column>
<Column field="price" header="Price" :sortable="true" style="width: 35%">
<template #body="slotProps">
{{ formatCurrency(slotProps.data.price) }}
</template>
</Column>
<Column style="width: 15%" header="View">
<template #body>
<Button icon="pi pi-search" type="button" class="p-button-text"></Button>
</template>
</Column>
</DataTable>
</div>
<div class="card">
<div class="flex justify-between items-center mb-8">
<div class="font-semibold text-xl mb-4">Best Selling Products</div>
<div>
<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>
<ul class="list-none p-0 m-0">
<li class="flex flex-col md:flex-row md:items-center md:justify-between mb-6">
<div>
<span class="text-surface-900 dark:text-surface-0 font-medium mr-2 mb-1 md:mb-0">Space T-Shirt</span>
<div class="mt-1 text-muted-color">Clothing</div>
</div>
<div class="mt-2 md:mt-0 flex items-center">
<div class="bg-surface-300 dark:bg-surface-500 rounded-border overflow-hidden w-40 lg:w-24" style="height: 8px">
<div class="bg-orange-500 h-full" style="width: 50%"></div>
</div>
<span class="text-orange-500 ml-4 font-medium">%50</span>
</div>
</li>
<li class="flex flex-col md:flex-row md:items-center md:justify-between mb-6">
<div>
<span class="text-surface-900 dark:text-surface-0 font-medium mr-2 mb-1 md:mb-0">Portal Sticker</span>
<div class="mt-1 text-muted-color">Accessories</div>
</div>
<div class="mt-2 md:mt-0 ml-0 md:ml-20 flex items-center">
<div class="bg-surface-300 dark:bg-surface-500 rounded-border overflow-hidden w-40 lg:w-24" style="height: 8px">
<div class="bg-cyan-500 h-full" style="width: 16%"></div>
</div>
<span class="text-cyan-500 ml-4 font-medium">%16</span>
</div>
</li>
<li class="flex flex-col md:flex-row md:items-center md:justify-between mb-6">
<div>
<span class="text-surface-900 dark:text-surface-0 font-medium mr-2 mb-1 md:mb-0">Supernova Sticker</span>
<div class="mt-1 text-muted-color">Accessories</div>
</div>
<div class="mt-2 md:mt-0 ml-0 md:ml-20 flex items-center">
<div class="bg-surface-300 dark:bg-surface-500 rounded-border overflow-hidden w-40 lg:w-24" style="height: 8px">
<div class="bg-pink-500 h-full" style="width: 67%"></div>
</div>
<span class="text-pink-500 ml-4 font-medium">%67</span>
</div>
</li>
<li class="flex flex-col md:flex-row md:items-center md:justify-between mb-6">
<div>
<span class="text-surface-900 dark:text-surface-0 font-medium mr-2 mb-1 md:mb-0">Wonders Notebook</span>
<div class="mt-1 text-muted-color">Office</div>
</div>
<div class="mt-2 md:mt-0 ml-0 md:ml-20 flex items-center">
<div class="bg-surface-300 dark:bg-surface-500 rounded-border overflow-hidden w-40 lg:w-24" style="height: 8px">
<div class="bg-green-500 h-full" style="width: 35%"></div>
</div>
<span class="text-primary ml-4 font-medium">%35</span>
</div>
</li>
<li class="flex flex-col md:flex-row md:items-center md:justify-between mb-6">
<div>
<span class="text-surface-900 dark:text-surface-0 font-medium mr-2 mb-1 md:mb-0">Mat Black Case</span>
<div class="mt-1 text-muted-color">Accessories</div>
</div>
<div class="mt-2 md:mt-0 ml-0 md:ml-20 flex items-center">
<div class="bg-surface-300 dark:bg-surface-500 rounded-border overflow-hidden w-40 lg:w-24" style="height: 8px">
<div class="bg-purple-500 h-full" style="width: 75%"></div>
</div>
<span class="text-purple-500 ml-4 font-medium">%75</span>
</div>
</li>
<li class="flex flex-col md:flex-row md:items-center md:justify-between mb-6">
<div>
<span class="text-surface-900 dark:text-surface-0 font-medium mr-2 mb-1 md:mb-0">Robots T-Shirt</span>
<div class="mt-1 text-muted-color">Clothing</div>
</div>
<div class="mt-2 md:mt-0 ml-0 md:ml-20 flex items-center">
<div class="bg-surface-300 dark:bg-surface-500 rounded-border overflow-hidden w-40 lg:w-24" style="height: 8px">
<div class="bg-teal-500 h-full" style="width: 40%"></div>
</div>
<span class="text-teal-500 ml-4 font-medium">%40</span>
</div>
</li>
</ul>
</div>
</div>
<div class="col-span-12 xl:col-span-6">
<div class="card">
<div class="font-semibold text-xl mb-4">Sales Overview</div>
<Chart type="bar" :data="chartData" :options="chartOptions" class="h-80" />
</div>
<div class="card">
<div class="flex items-center justify-between mb-6">
<div class="font-semibold text-xl mb-4">Notifications</div>
<div>
<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>
<span class="block text-muted-color font-medium mb-4">TODAY</span>
<ul class="p-0 mx-0 mt-0 mb-6 list-none">
<li class="flex items-center py-2 border-b border-surface">
<div class="w-12 h-12 flex items-center justify-center bg-blue-100 rounded-full mr-4 shrink-0">
<i class="pi pi-dollar text-xl text-blue-500"></i>
</div>
<span class="text-surface-900 dark:text-surface-0 leading-normal"
>Richard Jones
<span class="text-surface-700 dark:text-surface-100">has purchased a blue t-shirt for <span class="text-blue-500">79$</span></span>
</span>
</li>
<li class="flex items-center py-2">
<div class="w-12 h-12 flex items-center justify-center bg-orange-100 rounded-full mr-4 shrink-0">
<i class="pi pi-download text-xl text-orange-500"></i>
</div>
<span class="text-surface-700 dark:text-surface-100 leading-normal">Your request for withdrawal of <span class="text-blue-500 font-medium">2500$</span> has been initiated.</span>
</li>
</ul>
<span class="block text-muted-color font-medium mb-4">YESTERDAY</span>
<ul class="p-0 m-0 list-none">
<li class="flex items-center py-2 border-b border-surface">
<div class="w-12 h-12 flex items-center justify-center bg-blue-100 rounded-full mr-4 shrink-0">
<i class="pi pi-dollar text-xl text-blue-500"></i>
</div>
<span class="text-surface-900 dark:text-surface-0 leading-normal"
>Keyser Wick
<span class="text-surface-700 dark:text-surface-100">has purchased a black jacket for <span class="text-blue-500">59$</span></span>
</span>
</li>
<li class="flex items-center py-2 border-b border-surface">
<div class="w-12 h-12 flex items-center justify-center bg-pink-100 rounded-full mr-4 shrink-0">
<i class="pi pi-question text-xl text-pink-500"></i>
</div>
<span class="text-surface-900 dark:text-surface-0 leading-normal"
>Jane Davis
<span class="text-surface-700 dark:text-surface-100">has posted a new questions about your product.</span>
</span>
</li>
</ul>
</div>
</div>
</div>
</template>

280
src/views/pages/Crud.vue Normal file
View File

@@ -0,0 +1,280 @@
<script setup>
import { ref, onMounted } from 'vue';
import { FilterMatchMode } from '@primevue/core/api';
import { useToast } from 'primevue/usetoast';
import { ProductService } from '@/service/ProductService';
onMounted(() => {
ProductService.getProducts().then((data) => (products.value = data));
});
const toast = useToast();
const dt = ref();
const products = ref();
const productDialog = ref(false);
const deleteProductDialog = ref(false);
const deleteProductsDialog = ref(false);
const product = ref({});
const selectedProducts = ref();
const filters = ref({
global: { value: null, matchMode: FilterMatchMode.CONTAINS }
});
const submitted = ref(false);
const statuses = ref([
{ label: 'INSTOCK', value: 'instock' },
{ label: 'LOWSTOCK', value: 'lowstock' },
{ label: 'OUTOFSTOCK', value: 'outofstock' }
]);
const formatCurrency = (value) => {
if (value) return value.toLocaleString('en-US', { style: 'currency', currency: 'USD' });
return;
};
const openNew = () => {
product.value = {};
submitted.value = false;
productDialog.value = true;
};
const hideDialog = () => {
productDialog.value = false;
submitted.value = false;
};
const saveProduct = () => {
submitted.value = true;
if (product?.value.name?.trim()) {
if (product.value.id) {
product.value.inventoryStatus = product.value.inventoryStatus.value ? product.value.inventoryStatus.value : product.value.inventoryStatus;
products.value[findIndexById(product.value.id)] = product.value;
toast.add({ severity: 'success', summary: 'Successful', detail: 'Product Updated', life: 3000 });
} else {
product.value.id = createId();
product.value.code = createId();
product.value.image = 'product-placeholder.svg';
product.value.inventoryStatus = product.value.inventoryStatus ? product.value.inventoryStatus.value : 'INSTOCK';
products.value.push(product.value);
toast.add({ severity: 'success', summary: 'Successful', detail: 'Product Created', life: 3000 });
}
productDialog.value = false;
product.value = {};
}
};
const editProduct = (prod) => {
product.value = { ...prod };
productDialog.value = true;
};
const confirmDeleteProduct = (prod) => {
product.value = prod;
deleteProductDialog.value = true;
};
const deleteProduct = () => {
products.value = products.value.filter((val) => val.id !== product.value.id);
deleteProductDialog.value = false;
product.value = {};
toast.add({ severity: 'success', summary: 'Successful', detail: 'Product Deleted', life: 3000 });
};
const findIndexById = (id) => {
let index = -1;
for (let i = 0; i < products.value.length; i++) {
if (products.value[i].id === id) {
index = i;
break;
}
}
return index;
};
const createId = () => {
let id = '';
var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
for (var i = 0; i < 5; i++) {
id += chars.charAt(Math.floor(Math.random() * chars.length));
}
return id;
};
const exportCSV = () => {
dt.value.exportCSV();
};
const confirmDeleteSelected = () => {
deleteProductsDialog.value = true;
};
const deleteSelectedProducts = () => {
products.value = products.value.filter((val) => !selectedProducts.value.includes(val));
deleteProductsDialog.value = false;
selectedProducts.value = null;
toast.add({ severity: 'success', summary: 'Successful', detail: 'Products Deleted', life: 3000 });
};
const getStatusLabel = (status) => {
switch (status) {
case 'INSTOCK':
return 'success';
case 'LOWSTOCK':
return 'warn';
case 'OUTOFSTOCK':
return 'danger';
default:
return null;
}
};
</script>
<template>
<div>
<div class="card">
<Toolbar class="mb-6">
<template #start>
<Button label="New" icon="pi pi-plus" severity="success" class="mr-2" @click="openNew" />
<Button label="Delete" icon="pi pi-trash" severity="danger" @click="confirmDeleteSelected" :disabled="!selectedProducts || !selectedProducts.length" />
</template>
<template #end>
<FileUpload mode="basic" accept="image/*" :maxFileSize="1000000" label="Import" chooseLabel="Import" class="mr-2" auto />
<Button label="Export" icon="pi pi-upload" severity="help" @click="exportCSV($event)" />
</template>
</Toolbar>
<DataTable
ref="dt"
v-model:selection="selectedProducts"
:value="products"
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"
>
<template #header>
<div class="flex flex-wrap gap-2 items-center justify-between">
<h4 class="m-0">Manage Products</h4>
<IconField>
<InputIcon>
<i class="pi pi-search" />
</InputIcon>
<InputText v-model="filters['global'].value" placeholder="Search..." />
</IconField>
</div>
</template>
<Column selectionMode="multiple" style="width: 3rem" :exportable="false"></Column>
<Column field="code" header="Code" sortable style="min-width: 12rem"></Column>
<Column field="name" header="Name" sortable style="min-width: 16rem"></Column>
<Column header="Image">
<template #body="slotProps">
<img :src="`https://primefaces.org/cdn/primevue/images/product/${slotProps.data.image}`" :alt="slotProps.data.image" class="rounded" style="width: 64px" />
</template>
</Column>
<Column field="price" header="Price" sortable style="min-width: 8rem">
<template #body="slotProps">
{{ formatCurrency(slotProps.data.price) }}
</template>
</Column>
<Column field="category" header="Category" sortable style="min-width: 10rem"></Column>
<Column field="rating" header="Reviews" sortable style="min-width: 12rem">
<template #body="slotProps">
<Rating :modelValue="slotProps.data.rating" :readonly="true" />
</template>
</Column>
<Column field="inventoryStatus" header="Status" sortable style="min-width: 12rem">
<template #body="slotProps">
<Tag :value="slotProps.data.inventoryStatus" :severity="getStatusLabel(slotProps.data.inventoryStatus)" />
</template>
</Column>
<Column :exportable="false" style="min-width: 12rem">
<template #body="slotProps">
<Button icon="pi pi-pencil" outlined rounded class="mr-2" @click="editProduct(slotProps.data)" />
<Button icon="pi pi-trash" outlined rounded severity="danger" @click="confirmDeleteProduct(slotProps.data)" />
</template>
</Column>
</DataTable>
</div>
<Dialog v-model:visible="productDialog" :style="{ width: '450px' }" header="Product Details" :modal="true">
<div class="flex flex-col gap-6">
<img v-if="product.image" :src="`https://primefaces.org/cdn/primevue/images/product/${product.image}`" :alt="product.image" class="block m-auto pb-4" />
<div>
<label for="name" class="block font-bold mb-3">Name</label>
<InputText id="name" v-model.trim="product.name" required="true" autofocus :invalid="submitted && !product.name" fluid />
<small v-if="submitted && !product.name" class="text-red-500">Name is required.</small>
</div>
<div>
<label for="description" class="block font-bold mb-3">Description</label>
<Textarea id="description" v-model="product.description" required="true" rows="3" cols="20" fluid />
</div>
<div>
<label for="inventoryStatus" class="block font-bold mb-3">Inventory Status</label>
<Select id="inventoryStatus" v-model="product.inventoryStatus" :options="statuses" optionLabel="label" placeholder="Select a Status" fluid></Select>
</div>
<div>
<span class="block font-bold mb-4">Category</span>
<div class="grid grid-cols-12 gap-4">
<div class="flex items-center gap-2 col-span-6">
<RadioButton id="category1" v-model="product.category" name="category" value="Accessories" />
<label for="category1">Accessories</label>
</div>
<div class="flex items-center gap-2 col-span-6">
<RadioButton id="category2" v-model="product.category" name="category" value="Clothing" />
<label for="category2">Clothing</label>
</div>
<div class="flex items-center gap-2 col-span-6">
<RadioButton id="category3" v-model="product.category" name="category" value="Electronics" />
<label for="category3">Electronics</label>
</div>
<div class="flex items-center gap-2 col-span-6">
<RadioButton id="category4" v-model="product.category" name="category" value="Fitness" />
<label for="category4">Fitness</label>
</div>
</div>
</div>
<div class="grid grid-cols-12 gap-4">
<div class="col-span-6">
<label for="price" class="block font-bold mb-3">Price</label>
<InputNumber id="price" v-model="product.price" mode="currency" currency="USD" locale="en-US" fluid />
</div>
<div class="col-span-6">
<label for="quantity" class="block font-bold mb-3">Quantity</label>
<InputNumber id="quantity" v-model="product.quantity" integeronly fluid />
</div>
</div>
</div>
<template #footer>
<Button label="Cancel" icon="pi pi-times" text @click="hideDialog" />
<Button label="Save" icon="pi pi-check" @click="saveProduct" />
</template>
</Dialog>
<Dialog v-model:visible="deleteProductDialog" :style="{ width: '450px' }" header="Confirm" :modal="true">
<div class="flex items-center gap-4">
<i class="pi pi-exclamation-triangle !text-3xl" />
<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" />
<Button label="Yes" icon="pi pi-check" @click="deleteProduct" />
</template>
</Dialog>
<Dialog v-model:visible="deleteProductsDialog" :style="{ width: '450px' }" header="Confirm" :modal="true">
<div class="flex items-center gap-4">
<i class="pi pi-exclamation-triangle !text-3xl" />
<span v-if="product">Are you sure you want to delete the selected products?</span>
</div>
<template #footer>
<Button label="No" icon="pi pi-times" text @click="deleteProductsDialog = false" />
<Button label="Yes" icon="pi pi-check" text @click="deleteSelectedProducts" />
</template>
</Dialog>
</div>
</template>

View File

@@ -0,0 +1,6 @@
<template>
<div className="card">
<h5>Empty Page</h5>
<p>Use this page to start from scratch and place your custom content.</p>
</div>
</template>

View File

@@ -0,0 +1,87 @@
<template>
<div className="card">
<h5>Ks document</h5>
<form @submit.prevent="submitForm">
<div class="p-field">
<label for="description">Description</label>
<InputText id="description" v-model="ksdocument.description" />
</div>
<div class="p-field">
<label for="fileName">File Name</label>
<InputText id="fileName" v-model="ksdocument.fileName" />
</div>
<div class="p-field">
<label for="filePath">File Path</label>
<InputText id="filePath" v-model="ksdocument.filePath" />
</div>
<div class="p-field">
<label for="ingestionDate">Ingestion Date</label>
<InputText id="ingestionDate" v-model="ksdocument.ingestionDate" />
</div>
<div class="p-field">
<label for="defaultChunkSize">Default Chunk Size</label>
<InputNumber id="defaultChunkSize" v-model="ksdocument.ingestionInfo.defaultChunkSize" />
</div>
<div class="p-field">
<label for="maxNumberOfChunks">Max Number of Chunks</label>
<InputNumber id="maxNumberOfChunks" v-model="ksdocument.ingestionInfo.maxNumberOfChunks" />
</div>
<div class="p-field">
<label for="minChunkSize">Min Chunk Size</label>
<InputNumber id="minChunkSize" v-model="ksdocument.ingestionInfo.minChunkSize" />
</div>
<div class="p-field">
<label for="minChunkSizeToEmbed">Min Chunk Size To Embed</label>
<InputNumber id="minChunkSizeToEmbed" v-model="ksdocument.ingestionInfo.minChunkSizeToEmbed" />
</div>
<div class="p-field">
<label for="type">Type</label>
<InputText id="type" v-model="ksdocument.ingestionInfo.type" />
</div>
<div class="p-field">
<label for="ingestionStatus">Ingestion Status</label>
<InputText id="ingestionStatus" v-model="ksdocument.ingestionStatus" />
</div>
<div class="p-field">
<label for="name">Name</label>
<InputText id="name" v-model="ksdocument.name" />
</div>
<div class="p-field">
<label for="metadata">Metadata</label>
<InputTextarea id="metadata" v-model="ksdocument.ingestionInfo.metadata" />
</div>
<Button label="Submit" type="submit" />
</form>
</div>
</template>
<script setup>
import { ref } from 'vue';
import { onMounted } from 'vue'
import axios from 'axios';
import { useRoute, useRouter } from 'vue-router'
import { data } from 'autoprefixer';
const route = useRoute()
const ksdocument = ref({ingestionInfo:{}});
onMounted(() => {
axios.get('http://localhost:8082/ksdocuments/'+route.params.id)
.then(response => {
console.log(response.data);
ksdocument.value = response.data;
});
});
const getStatus = (data) => {
if (data.ingestionStatus === 'INGESTED') {
return 'success';
} else if (data.ingestionStatus === 'NEW') {
return 'danger';
} else {
return 'warning';
}
}
</script>

View File

@@ -0,0 +1,74 @@
<template>
<div className="card">
<DataTable
:value="ksdocuments"
:paginator="true"
:rows="10"
dataKey="id"
:rowHover="true"
showGridlines
>
<template #header>
<div class="flex flex-wrap items-center justify-between gap-2">
<span class="text-xl font-bold">KS Documents</span>
<Button icon="pi pi-plus" rounded raised @click="newKsDocument()" />
</div>
</template>
<Column field="name" header="Name"></Column>
<Column field="fileName" header="File Name"></Column>
<Column field="ingestionStatus" header="Status">
<template #body="slotProps">
<Tag :value="slotProps.data.ingestionStatus" :severity="getStatus(slotProps.data)" />
</template>
</Column>
<Column field="ingestionDate" header="Ingestion Date"></Column>
<Column headerStyle="width: 5rem; text-align: center" bodyStyle="text-align: center; overflow: visible">
<template #body="slotProps">
<Button type="button" icon="pi pi-pencil" rounded @click="editKsDocument(slotProps.data)"/>
</template>
</Column>
</DataTable>
</div>
</template>
<script setup>
import { ref } from 'vue';
import { onMounted } from 'vue'
import axios from 'axios';
import { useRoute, useRouter } from 'vue-router'
import { data } from 'autoprefixer';
const router = useRouter()
const ksdocuments = ref(null);
onMounted(() => {
axios.get('http://localhost:8082/fe-api/ksdocuments')
.then(response => {
console.log(response.data);
ksdocuments.value = response.data;
});
});
const getStatus = (data) => {
if (data.ingestionStatus === 'INGESTED') {
return 'success';
} else if (data.ingestionStatus === 'NEW') {
return 'danger';
} else {
return 'warning';
}
}
const editKsDocument = (data) => {
console.log(data);
router.push({ name: 'ks-document-edit', params: { id: data.id } });
}
const newKsDocument = () => {
console.log('new');
router.push({ name: 'ks-document-new'});
}
</script>

455
src/views/pages/Landing.vue Normal file
View File

@@ -0,0 +1,455 @@
<script setup>
import { useLayout } from '@/layout/composables/layout';
import { computed } from 'vue';
const { isDarkTheme } = useLayout();
const smoothScroll = (id) => {
document.querySelector(id).scrollIntoView({
behavior: 'smooth'
});
};
const logoUrl = computed(() => {
return `layout/images/${isDarkTheme ? 'logo-white' : 'logo-dark'}.svg`;
});
</script>
<template>
<div class="bg-surface-0 dark:bg-surface-900 flex justify-center">
<div id="home" class="landing-wrapper overflow-hidden">
<div class="py-6 px-6 mx-0 md:mx-12 lg:mx-20 lg:px-20 flex items-center justify-between relative lg:static mb-4">
<a class="flex items-center" href="#"> <img :src="logoUrl" alt="Sakai Logo" height="50" class="mr-0 lg:mr-2" /><span class="text-surface-900 dark:text-surface-0 font-medium text-2xl leading-normal mr-20">SAKAI</span> </a>
<a class="cursor-pointer block lg:hidden text-surface-700 dark:text-surface-100 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="items-center bg-surface-0 dark:bg-surface-900 grow justify-between hidden lg:flex absolute lg:static w-full left-0 px-12 lg:px-0 z-20" style="top: 120px">
<ul class="list-none p-0 m-0 flex lg:items-center select-none flex-col lg:flex-row cursor-pointer">
<li>
<a @click="smoothScroll('#hero')" class="flex m-0 md:ml-8 px-0 py-4 text-surface-900 dark:text-surface-0 font-medium leading-normal p-ripple" v-ripple>
<span>Home</span>
</a>
</li>
<li>
<a @click="smoothScroll('#features')" class="flex m-0 md:ml-8 px-0 py-4 text-surface-900 dark:text-surface-0 font-medium leading-normal p-ripple" v-ripple>
<span>Features</span>
</a>
</li>
<li>
<a @click="smoothScroll('#highlights')" class="flex m-0 md:ml-8 px-0 py-4 text-surface-900 dark:text-surface-0 font-medium leading-normal p-ripple" v-ripple>
<span>Highlights</span>
</a>
</li>
<li>
<a @click="smoothScroll('#pricing')" class="flex m-0 md:ml-8 px-0 py-4 text-surface-900 dark:text-surface-0 font-medium leading-normal p-ripple" v-ripple>
<span>Pricing</span>
</a>
</li>
</ul>
<div class="flex justify-between lg:block border-t lg:border-t-0 border-surface py-4 lg:py-0 mt-4 lg:mt-0">
<Button label="Login" class="p-button-text p-button-rounded border-0 font-light leading-tight text-blue-500"></Button>
<Button label="Register" class="p-button-rounded border-0 ml-8 font-light text-white leading-tight bg-blue-500"></Button>
</div>
</div>
</div>
<div
id="hero"
class="flex flex-col pt-6 px-6 lg:px-20 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-6 md:mx-20 mt-0 md:mt-6">
<h1 class="text-6xl font-bold text-gray-900 leading-tight"><span class="font-light block">Eu sem integer</span>eget magna fermentum</h1>
<p class="font-normal text-2xl leading-normal md:mt-4 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-0 mt-8 bg-blue-500 font-normal text-white leading-normal px-4"></Button>
</div>
<div class="flex justify-center md:justify-end">
<img src="/demo/images/landing/screen-1.png" alt="Hero Image" class="w-9/12 md:w-auto" />
</div>
</div>
<div id="features" class="py-6 px-6 lg:px-20 mt-8 mx-0 lg:mx-20">
<div class="grid grid-cols-12 gap-4 justify-center">
<div class="col-span-12 text-center mt-20 mb-6">
<h2 class="text-surface-900 dark:text-surface-0 font-normal mb-2">Marvelous Features</h2>
<span class="text-surface-600 dark:text-surface-200 text-2xl">Placerat in egestas erat...</span>
</div>
<div class="col-span-12 md:col-span-12 lg:col-span-4 p-0 lg:pr-8 lg:pb-8 mt-6 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))"
>
<div class="p-4 bg-surface-0 dark:bg-surface-900 h-full" style="border-radius: 8px">
<div class="flex items-center justify-center bg-yellow-200 mb-4" 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-surface-900 dark:text-surface-0">Easy to Use</h5>
<span class="text-surface-600 dark:text-surface-200">Posuere morbi leo urna molestie.</span>
</div>
</div>
</div>
<div class="col-span-12 md:col-span-12 lg:col-span-4 p-0 lg:pr-8 lg:pb-8 mt-6 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))"
>
<div class="p-4 bg-surface-0 dark:bg-surface-900 h-full" style="border-radius: 8px">
<div class="flex items-center justify-center bg-cyan-200 mb-4" 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-surface-900 dark:text-surface-0">Fresh Design</h5>
<span class="text-surface-600 dark:text-surface-200">Semper risus in hendrerit.</span>
</div>
</div>
</div>
<div class="col-span-12 md:col-span-12 lg:col-span-4 p-0 lg:pb-8 mt-6 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))"
>
<div class="p-4 bg-surface-0 dark:bg-surface-900 h-full" style="border-radius: 8px">
<div class="flex items-center justify-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-surface-900 dark:text-surface-0">Well Documented</h5>
<span class="text-surface-600 dark:text-surface-200">Non arcu risus quis varius quam quisque.</span>
</div>
</div>
</div>
<div class="col-span-12 md:col-span-12 lg:col-span-4 p-0 lg:pr-8 lg:pb-8 mt-6 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))"
>
<div class="p-4 bg-surface-0 dark:bg-surface-900 h-full" style="border-radius: 8px">
<div class="flex items-center justify-center bg-slate-200 mb-4" style="width: 3.5rem; height: 3.5rem; border-radius: 10px">
<i class="pi pi-fw pi-id-card text-2xl text-slate-700"></i>
</div>
<h5 class="mb-2 text-surface-900 dark:text-surface-0">Responsive Layout</h5>
<span class="text-surface-600 dark:text-surface-200">Nulla malesuada pellentesque elit.</span>
</div>
</div>
</div>
<div class="col-span-12 md:col-span-12 lg:col-span-4 p-0 lg:pr-8 lg:pb-8 mt-6 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))"
>
<div class="p-4 bg-surface-0 dark:bg-surface-900 h-full" style="border-radius: 8px">
<div class="flex items-center justify-center bg-orange-200 mb-4" 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-surface-900 dark:text-surface-0">Clean Code</h5>
<span class="text-surface-600 dark:text-surface-200">Condimentum lacinia quis vel eros.</span>
</div>
</div>
</div>
<div class="col-span-12 md:col-span-12 lg:col-span-4 p-0 lg:pb-8 mt-6 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))"
>
<div class="p-4 bg-surface-0 dark:bg-surface-900 h-full" style="border-radius: 8px">
<div class="flex items-center justify-center bg-pink-200 mb-4" 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-surface-900 dark:text-surface-0">Dark Mode</h5>
<span class="text-surface-600 dark:text-surface-200">Convallis tellus id interdum velit laoreet.</span>
</div>
</div>
</div>
<div class="col-span-12 md:col-span-12 lg:col-span-4 p-0 lg:pr-8 mt-6 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))"
>
<div class="p-4 bg-surface-0 dark:bg-surface-900 h-full" style="border-radius: 8px">
<div class="flex items-center justify-center bg-teal-200 mb-4" 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-surface-900 dark:text-surface-0">Ready to Use</h5>
<span class="text-surface-600 dark:text-surface-200">Mauris sit amet massa vitae.</span>
</div>
</div>
</div>
<div class="col-span-12 md:col-span-12 lg:col-span-4 p-0 lg:pr-8 mt-6 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))"
>
<div class="p-4 bg-surface-0 dark:bg-surface-900 h-full" style="border-radius: 8px">
<div class="flex items-center justify-center bg-blue-200 mb-4" 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-surface-900 dark:text-surface-0">Modern Practices</h5>
<span class="text-surface-600 dark:text-surface-200">Elementum nibh tellus molestie nunc non.</span>
</div>
</div>
</div>
<div class="col-span-12 md:col-span-12 lg:col-span-4 p-0 lg-4 mt-6 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))"
>
<div class="p-4 bg-surface-0 dark:bg-surface-900 h-full" style="border-radius: 8px">
<div class="flex items-center justify-center bg-purple-200 mb-4" 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-surface-900 dark:text-surface-0">Privacy</h5>
<span class="text-surface-600 dark:text-surface-200">Neque egestas congue quisque.</span>
</div>
</div>
</div>
<div
class="col-span-12 mt-20 mb-20 p-2 md:p-20"
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-col justify-center items-center text-center px-4 py-4 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-6" 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-6" alt="Company logo" />
</div>
</div>
</div>
</div>
<div id="highlights" class="py-6 px-6 lg:px-20 mx-0 my-12 lg:mx-20">
<div class="text-center">
<h2 class="text-surface-900 dark:text-surface-0 font-normal mb-2">Powerful Everywhere</h2>
<span class="text-surface-600 dark:text-surface-200 text-2xl">Amet consectetur adipiscing elit...</span>
</div>
<div class="grid grid-cols-12 gap-4 mt-20 pb-2 md:pb-20">
<div class="flex justify-center col-span-12 lg:col-span-6 bg-purple-100 p-0 order-1 lg:order-none" style="border-radius: 8px">
<img src="/demo/images/landing/mockup.svg" class="w-11/12" alt="mockup mobile" />
</div>
<div class="col-span-12 lg:col-span-6 my-auto flex flex-col lg:items-end text-center lg:text-right">
<div class="flex items-center justify-center bg-purple-200 self-center lg: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="leading-none text-surface-900 dark:text-surface-0 text-4xl font-normal">Congue Quisque Egestas</h2>
<span class="text-surface-700 dark:text-surface-100 text-2xl leading-normal 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 grid-cols-12 gap-4 my-20 pt-2 md:pt-20">
<div class="col-span-12 lg:col-span-6 my-auto flex flex-col text-center lg:text-left lg:items-start">
<div class="flex items-center justify-center bg-yellow-200 self-center lg: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="leading-none text-surface-900 dark:text-surface-0 text-4xl font-normal">Celerisque Eu Ultrices</h2>
<span class="text-surface-700 dark:text-surface-100 text-2xl leading-normal 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-end order-1 sm:order-2 col-span-12 lg:col-span-6 bg-yellow-100 p-0" style="border-radius: 8px">
<img src="/demo/images/landing/mockup-desktop.svg" class="w-11/12" alt="mockup" />
</div>
</div>
</div>
<div id="pricing" class="py-6 px-6 lg:px-20 my-2 md:my-6">
<div class="text-center">
<h2 class="text-surface-900 dark:text-surface-0 font-normal mb-2">Matchless Pricing</h2>
<span class="text-surface-600 dark:text-surface-200 text-2xl">Amet consectetur adipiscing elit...</span>
</div>
<div class="grid grid-cols-12 gap-4 justify-between mt-20 md:mt-0">
<div class="col-span-12 lg:col-span-4 p-0 md:p-4">
<div class="p-4 flex flex-col border-surface-200 dark:border-surface-600 pricing-card cursor-pointer border-2 hover:border-primary duration-300 transition-all" style="border-radius: 10px">
<h3 class="text-surface-900 dark:text-surface-0 text-center my-8">Free</h3>
<img src="/demo/images/landing/free.svg" class="w-10/12 h-10 mx-auto" alt="free" />
<div class="my-8 text-center">
<span class="text-5xl font-bold mr-2 text-surface-900 dark:text-surface-0">$0</span>
<span class="text-surface-600 dark:text-surface-200">per month</span>
<Button label="Get Started" class="block mx-auto mt-6 p-button-rounded border-0 ml-4 font-light leading-tight bg-blue-500 text-white"></Button>
</div>
<Divider class="w-full bg-surface-200"></Divider>
<ul class="my-8 list-none p-0 flex text-surface-900 dark:text-surface-0 flex-col">
<li class="py-2">
<i class="pi pi-fw pi-check text-xl text-cyan-500 mr-2"></i>
<span class="text-xl leading-normal">Responsive Layout</span>
</li>
<li class="py-2">
<i class="pi pi-fw pi-check text-xl text-cyan-500 mr-2"></i>
<span class="text-xl leading-normal">Unlimited Push Messages</span>
</li>
<li class="py-2">
<i class="pi pi-fw pi-check text-xl text-cyan-500 mr-2"></i>
<span class="text-xl leading-normal">50 Support Ticket</span>
</li>
<li class="py-2">
<i class="pi pi-fw pi-check text-xl text-cyan-500 mr-2"></i>
<span class="text-xl leading-normal">Free Shipping</span>
</li>
</ul>
</div>
</div>
<div class="col-span-12 lg:col-span-4 p-0 md:p-4 mt-6 md:mt-0">
<div class="p-4 flex flex-col border-surface-200 dark:border-surface-600 pricing-card cursor-pointer border-2 hover:border-primary duration-300 transition-all" style="border-radius: 10px">
<h3 class="text-surface-900 dark:text-surface-0 text-center my-8">Startup</h3>
<img src="/demo/images/landing/startup.svg" class="w-10/12 h-10 mx-auto" alt="startup" />
<div class="my-8 text-center">
<span class="text-5xl font-bold mr-2 text-surface-900 dark:text-surface-0">$1</span>
<span class="text-surface-600 dark:text-surface-200">per month</span>
<Button label="Try Free" class="block mx-auto mt-6 p-button-rounded border-0 ml-4 font-light leading-tight bg-blue-500 text-white"></Button>
</div>
<Divider class="w-full bg-surface-200"></Divider>
<ul class="my-8 list-none p-0 flex text-surface-900 dark:text-surface-0 flex-col">
<li class="py-2">
<i class="pi pi-fw pi-check text-xl text-cyan-500 mr-2"></i>
<span class="text-xl leading-normal">Responsive Layout</span>
</li>
<li class="py-2">
<i class="pi pi-fw pi-check text-xl text-cyan-500 mr-2"></i>
<span class="text-xl leading-normal">Unlimited Push Messages</span>
</li>
<li class="py-2">
<i class="pi pi-fw pi-check text-xl text-cyan-500 mr-2"></i>
<span class="text-xl leading-normal">50 Support Ticket</span>
</li>
<li class="py-2">
<i class="pi pi-fw pi-check text-xl text-cyan-500 mr-2"></i>
<span class="text-xl leading-normal">Free Shipping</span>
</li>
</ul>
</div>
</div>
<div class="col-span-12 lg:col-span-4 p-0 md:p-4 mt-6 md:mt-0">
<div class="p-4 flex flex-col border-surface-200 dark:border-surface-600 pricing-card cursor-pointer border-2 hover:border-primary duration-300 transition-all" style="border-radius: 10px">
<h3 class="text-surface-900 dark:text-surface-0 text-center my-8">Enterprise</h3>
<img src="/demo/images/landing/enterprise.svg" class="w-10/12 h-10 mx-auto" alt="enterprise" />
<div class="my-8 text-center">
<span class="text-5xl font-bold mr-2 text-surface-900 dark:text-surface-0">$999</span>
<span class="text-surface-600 dark:text-surface-200">per month</span>
<Button label="Get a Quote" class="block mx-auto mt-6 p-button-rounded border-0 ml-4 font-light leading-tight bg-blue-500 text-white"></Button>
</div>
<Divider class="w-full bg-surface-200"></Divider>
<ul class="my-8 list-none p-0 flex text-surface-900 dark:text-surface-0 flex-col">
<li class="py-2">
<i class="pi pi-fw pi-check text-xl text-cyan-500 mr-2"></i>
<span class="text-xl leading-normal">Responsive Layout</span>
</li>
<li class="py-2">
<i class="pi pi-fw pi-check text-xl text-cyan-500 mr-2"></i>
<span class="text-xl leading-normal">Unlimited Push Messages</span>
</li>
<li class="py-2">
<i class="pi pi-fw pi-check text-xl text-cyan-500 mr-2"></i>
<span class="text-xl leading-normal">50 Support Ticket</span>
</li>
<li class="py-2">
<i class="pi pi-fw pi-check text-xl text-cyan-500 mr-2"></i>
<span class="text-xl leading-normal">Free Shipping</span>
</li>
</ul>
</div>
</div>
</div>
</div>
<div class="py-6 px-6 mx-0 mt-20 lg:mx-20">
<div class="grid grid-cols-12 gap-4 justify-between">
<div class="col-span-12 md:col-span-2" style="margin-top: -1.5rem">
<a @click="smoothScroll('#home')" class="flex flex-wrap items-center justify-center md:justify-start md:mb-0 mb-4 cursor-pointer">
<img :src="logoUrl" alt="footer sections" width="50" height="50" class="mr-2" />
<h4 class="font-medium text-3xl text-surface-900 dark:text-surface-0">SAKAI</h4>
</a>
</div>
<div class="col-span-12 md:col-span-10 lg:col-span-7">
<div class="grid grid-cols-12 gap-4 text-center md:text-left">
<div class="col-span-12 md:col-span-3">
<h4 class="font-medium text-2xl leading-normal mb-4 text-surface-900 dark:text-surface-0">Company</h4>
<a class="leading-normal text-xl block cursor-pointer mb-2 text-surface-700 dark:text-surface-100">About Us</a>
<a class="leading-normal text-xl block cursor-pointer mb-2 text-surface-700 dark:text-surface-100">News</a>
<a class="leading-normal text-xl block cursor-pointer mb-2 text-surface-700 dark:text-surface-100">Investor Relations</a>
<a class="leading-normal text-xl block cursor-pointer mb-2 text-surface-700 dark:text-surface-100">Careers</a>
<a class="leading-normal text-xl block cursor-pointer text-surface-700 dark:text-surface-100">Media Kit</a>
</div>
<div class="col-span-12 md:col-span-3 mt-6 md:mt-0">
<h4 class="font-medium text-2xl leading-normal mb-4 text-surface-900 dark:text-surface-0">Resources</h4>
<a class="leading-normal text-xl block cursor-pointer mb-2 text-surface-700 dark:text-surface-100">Get Started</a>
<a class="leading-normal text-xl block cursor-pointer mb-2 text-surface-700 dark:text-surface-100">Learn</a>
<a class="leading-normal text-xl block cursor-pointer text-surface-700 dark:text-surface-100">Case Studies</a>
</div>
<div class="col-span-12 md:col-span-3 mt-6 md:mt-0">
<h4 class="font-medium text-2xl leading-normal mb-4 text-surface-900 dark:text-surface-0">Community</h4>
<a class="leading-normal text-xl block cursor-pointer mb-2 text-surface-700 dark:text-surface-100">Discord</a>
<a class="leading-normal text-xl block cursor-pointer mb-2 text-surface-700 dark:text-surface-100">Events<img src="/demo/images/landing/new-badge.svg" class="ml-2" /></a>
<a class="leading-normal text-xl block cursor-pointer mb-2 text-surface-700 dark:text-surface-100">FAQ</a>
<a class="leading-normal text-xl block cursor-pointer text-surface-700 dark:text-surface-100">Blog</a>
</div>
<div class="col-span-12 md:col-span-3 mt-6 md:mt-0">
<h4 class="font-medium text-2xl leading-normal mb-4 text-surface-900 dark:text-surface-0">Legal</h4>
<a class="leading-normal text-xl block cursor-pointer mb-2 text-surface-700 dark:text-surface-100">Brand Policy</a>
<a class="leading-normal text-xl block cursor-pointer mb-2 text-surface-700 dark:text-surface-100">Privacy Policy</a>
<a class="leading-normal text-xl block cursor-pointer text-surface-700 dark:text-surface-100">Terms of Service</a>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<!-- <style scoped>
#hero {
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%, #eeefaf 0%, #c3e3fa 100%);
height: 700px;
overflow: hidden;
}
@media screen and (min-width: 768px) {
#hero {
-webkit-clip-path: ellipse(150% 87% at 93% 13%);
clip-path: ellipse(150% 87% at 93% 13%);
height: 530px;
}
}
@media screen and (min-width: 1300px) {
#hero > img {
position: absolute;
}
#hero > div > p {
max-width: 450px;
}
}
@media screen and (max-width: 1300px) {
#hero {
height: 600px;
}
#hero > img {
position: static;
transform: scale(1);
margin-left: auto;
}
#hero > div {
width: 100%;
}
#hero > div > p {
width: 100%;
max-width: 100%;
}
}
</style> -->

View File

@@ -0,0 +1,43 @@
<script setup></script>
<template>
<div class="bg-surface-50 dark:bg-surface-950 flex items-center justify-center min-h-screen min-w-[100vw] overflow-hidden">
<div class="flex flex-col items-center justify-center">
<img src="/demo/images/notfound/logo-blue.svg" alt="Sakai logo" class="mb-8 w-24 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 bg-surface-0 dark:bg-surface-900 py-20 px-8 sm:px-20 flex flex-col items-center" style="border-radius: 53px">
<span class="text-blue-500 font-bold text-3xl">404</span>
<h1 class="text-surface-900 dark:text-surface-0 font-bold text-3xl lg:text-5xl mb-2">Not Found</h1>
<div class="text-surface-600 dark:text-surface-200 mb-8">Requested resource is not available.</div>
<router-link to="/" class="w-full flex items-center py-8 border-surface-300 dark:border-surface-500 border-b">
<span class="flex justify-center items-center bg-cyan-400 rounded-border" style="height: 3.5rem; width: 3.5rem">
<i class="text-surface-50 dark:text-surface-800 pi pi-fw pi-table text-2xl"></i>
</span>
<span class="ml-6 flex flex-col">
<span class="text-surface-900 dark:text-surface-0 lg:text-xl font-medium mb-0 block">Frequently Asked Questions</span>
<span class="text-surface-600 dark:text-surface-200 lg:text-xl">Ultricies mi quis hendrerit dolor.</span>
</span>
</router-link>
<router-link to="/" class="w-full flex items-center py-8 border-surface-300 dark:border-surface-500 border-b">
<span class="flex justify-center items-center bg-orange-400 rounded-border" style="height: 3.5rem; width: 3.5rem">
<i class="pi pi-fw pi-question-circle text-surface-50 dark:text-surface-800 text-2xl"></i>
</span>
<span class="ml-6 flex flex-col">
<span class="text-surface-900 dark:text-surface-0 lg:text-xl font-medium mb-0">Solution Center</span>
<span class="text-surface-600 dark:text-surface-200 lg:text-xl">Phasellus faucibus scelerisque eleifend.</span>
</span>
</router-link>
<router-link to="/" class="w-full flex items-center mb-8 py-8 border-surface-300 dark:border-surface-500 border-b">
<span class="flex justify-center items-center bg-indigo-400 rounded-border" style="height: 3.5rem; width: 3.5rem">
<i class="pi pi-fw pi-unlock text-surface-50 dark:text-surface-800 text-2xl"></i>
</span>
<span class="ml-6 flex flex-col">
<span class="text-surface-900 dark:text-surface-0 lg:text-xl font-medium mb-0">Permission Manager</span>
<span class="text-surface-600 dark:text-surface-200 lg:text-xl">Accumsan in nisl nisi scelerisque</span>
</span>
</router-link>
</div>
</div>
</div>
</div>
</template>

View File

@@ -0,0 +1,155 @@
<script setup>
import { ref } from 'vue';
const events = ref([
{
status: 'Ordered',
date: '15/10/2020 10:30',
icon: 'pi pi-shopping-cart',
color: '#9C27B0',
image: 'game-controller.jpg'
},
{
status: 'Processing',
date: '15/10/2020 14:00',
icon: 'pi pi-cog',
color: '#673AB7'
},
{
status: 'Shipped',
date: '15/10/2020 16:15',
icon: 'pi pi-envelope',
color: '#FF9800'
},
{
status: 'Delivered',
date: '16/10/2020 10:00',
icon: 'pi pi-check',
color: '#607D8B'
}
]);
const horizontalEvents = ref(['2020', '2021', '2022', '2023']);
</script>
<template>
<div class="grid grid-cols-12 gap-4">
<div class="col-span-6">
<div class="card">
<h5>Left Align</h5>
<Timeline :value="events">
<template #content="slotProps">
{{ slotProps.item.status }}
</template>
</Timeline>
</div>
</div>
<div class="col-span-6">
<div class="card">
<h5>Right Align</h5>
<Timeline :value="events" align="right">
<template #content="slotProps">
{{ slotProps.item.status }}
</template>
</Timeline>
</div>
</div>
<div class="col-span-6">
<div class="card">
<h5>Alternate Align</h5>
<Timeline :value="events" align="alternate">
<template #content="slotProps">
{{ slotProps.item.status }}
</template>
</Timeline>
</div>
</div>
<div class="col-span-6">
<div class="card">
<h5>Opposite Content</h5>
<Timeline :value="events">
<template #opposite="slotProps">
<small class="p-text-secondary">{{ slotProps.item.date }}</small>
</template>
<template #content="slotProps">
{{ slotProps.item.status }}
</template>
</Timeline>
</div>
</div>
</div>
<div class="card">
<h5>Custom Timeline</h5>
<Timeline :value="events" align="alternate" class="customized-timeline">
<template #marker="slotProps">
<span class="flex w-8 h-8 items-center justify-center text-white rounded-full z-10 shadow-sm" :style="{ backgroundColor: slotProps.item.color }">
<i :class="slotProps.item.icon"></i>
</span>
</template>
<template #content="slotProps">
<Card class="mt-4">
<template #title>
{{ slotProps.item.status }}
</template>
<template #subtitle>
{{ slotProps.item.date }}
</template>
<template #content>
<img v-if="slotProps.item.image" :src="`https://primefaces.org/cdn/primevue/images/product/${slotProps.item.image}`" :alt="slotProps.item.name" width="200" class="shadow-sm" />
<p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Inventore sed consequuntur error repudiandae numquam deserunt quisquam repellat libero asperiores earum nam nobis, culpa ratione quam perferendis esse, cupiditate
neque quas!
</p>
<Button label="Read more" text></Button>
</template>
</Card>
</template>
</Timeline>
</div>
<div class="card mt-4">
<h5>Horizontal</h5>
<h6>Top Align</h6>
<Timeline :value="horizontalEvents" layout="horizontal" align="top">
<template #content="slotProps">
{{ slotProps.item }}
</template>
</Timeline>
<h6>Bottom Align</h6>
<Timeline :value="horizontalEvents" layout="horizontal" align="bottom">
<template #content="slotProps">
{{ slotProps.item }}
</template>
</Timeline>
<h6>Alternate Align</h6>
<Timeline :value="horizontalEvents" layout="horizontal" align="alternate">
<template #opposite> &nbsp; </template>
<template #content="slotProps">
{{ slotProps.item }}
</template>
</Timeline>
</div>
</template>
<style lang="scss" scoped>
@media screen and (max-width: 960px) {
::v-deep(.customized-timeline) {
.p-timeline-event:nth-child(even) {
flex-direction: row !important;
.p-timeline-event-content {
text-align: left !important;
}
}
.p-timeline-event-opposite {
flex: 0;
}
.p-card {
margin-top: 1rem;
}
}
}
</style>

View File

@@ -0,0 +1,25 @@
<script setup></script>
<template>
<div class="bg-surface-50 dark:bg-surface-950 flex items-center justify-center min-h-screen min-w-[100vw] overflow-hidden">
<div class="flex flex-col items-center justify-center">
<img src="/demo/images/access/logo-orange.svg" alt="Sakai logo" class="mb-8 w-24 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 bg-surface-0 dark:bg-surface-900 py-20 px-8 sm:px-20 flex flex-col items-center" style="border-radius: 53px">
<div class="gap-4 flex flex-col items-center">
<div class="flex justify-center items-center bg-orange-500 rounded-full" style="width: 3.2rem; height: 3.2rem">
<i class="text-surface-50 dark:text-surface-800 pi pi-fw pi-lock text-2xl"></i>
</div>
<h1 class="text-surface-900 dark:text-surface-0 font-bold text-4xl lg:text-5xl mb-2">Access Denied</h1>
<span class="text-surface-600 dark:text-surface-200 mb-8">You do not have the necessary permisions. Please contact admins.</span>
<img src="/demo/images/access/asset-access.svg" alt="Access denied" class="mb-8" width="80%" />
<div class="col-span-12 mt-8 text-center">
<i class="pi pi-fw pi-arrow-left text-blue-500 mr-2" style="vertical-align: center"></i>
<router-link to="/" class="text-blue-500">Go to Dashboard</router-link>
</div>
</div>
</div>
</div>
</div>
</div>
</template>

View File

@@ -0,0 +1,25 @@
<script setup></script>
<template>
<div class="bg-surface-50 dark:bg-surface-950 flex items-center justify-center min-h-screen min-w-[100vw] overflow-hidden">
<div class="flex flex-col items-center justify-center">
<img src="/demo/images/error/logo-error.svg" alt="Sakai logo" class="mb-8 w-24 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 bg-surface-0 dark:bg-surface-900 py-20 px-8 sm:px-20 flex flex-col items-center" style="border-radius: 53px">
<div class="gap-4 flex flex-col items-center">
<div class="flex justify-center items-center bg-pink-500 rounded-full" style="height: 3.2rem; width: 3.2rem">
<i class="pi pi-fw pi-exclamation-circle text-2xl text-white"></i>
</div>
<h1 class="text-surface-900 dark:text-surface-0 font-bold text-5xl mb-2">Error Occured</h1>
<span class="text-surface-600 dark:text-surface-200 mb-8">Requested resource is not available.</span>
<img src="/demo/images/error/asset-error.svg" alt="Error" class="mb-8" width="80%" />
<div class="col-span-12 mt-8 text-center">
<i class="pi pi-fw pi-arrow-left text-blue-500 mr-2" style="vertical-align: center"></i>
<router-link to="/" class="text-blue-500">Go to Dashboard</router-link>
</div>
</div>
</div>
</div>
</div>
</div>
</template>

View File

@@ -0,0 +1,59 @@
<script setup>
import { useLayout } from '@/layout/composables/layout';
import { computed, ref } from 'vue';
const { isDarkTheme } = useLayout();
const email = ref('');
const password = ref('');
const checked = ref(false);
const logoUrl = computed(() => {
return `/layout/images/${isDarkTheme ? 'logo-white' : 'logo-dark'}.svg`;
});
</script>
<template>
<div class="bg-surface-50 dark:bg-surface-950 flex items-center justify-center min-h-screen min-w-[100vw] overflow-hidden">
<div class="flex flex-col items-center justify-center">
<img :src="logoUrl" alt="Sakai logo" class="mb-8 w-24 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 class="w-full bg-surface-0 dark:bg-surface-900 py-20 px-8 sm:px-20" style="border-radius: 53px">
<div class="text-center mb-8">
<img src="/demo/images/login/avatar.png" alt="Image" height="50" class="mb-4" />
<div class="text-surface-900 dark:text-surface-0 text-3xl font-medium mb-4">Welcome, Isabel!</div>
<span class="text-surface-600 dark:text-surface-200 font-medium">Sign in to continue</span>
</div>
<div>
<label for="email1" class="block text-surface-900 dark:text-surface-0 text-xl font-medium mb-2">Email</label>
<InputText id="email1" type="text" placeholder="Email address" class="w-full md:w-[30rem] mb-8" style="padding: 1rem" v-model="email" />
<label for="password1" class="block text-surface-900 dark:text-surface-0 font-medium text-xl mb-2">Password</label>
<Password id="password1" v-model="password" placeholder="Password" :toggleMask="true" class="w-full mb-4" inputClass="w-full" :inputStyle="{ padding: '1rem' }"></Password>
<div class="flex items-center justify-between mb-8 gap-8">
<div class="flex 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>
</div>
<Button label="Sign In" class="w-full p-4 text-xl"></Button>
</div>
</div>
</div>
</div>
</div>
</template>
<style scoped>
.pi-eye {
transform: scale(1.6);
margin-right: 1rem;
}
.pi-eye-slash {
transform: scale(1.6);
margin-right: 1rem;
}
</style>

View File

@@ -0,0 +1,198 @@
<script setup>
import { ref } from 'vue';
const items = ref([
{
label: 'Update',
icon: 'pi pi-refresh'
},
{
label: 'Delete',
icon: 'pi pi-times'
},
{
separator: true
},
{
label: 'Home',
icon: 'pi pi-home'
}
]);
const loading = ref([false, false, false]);
const load = (index) => {
loading.value[index] = true;
setTimeout(() => (loading.value[index] = false), 1000);
};
</script>
<template>
<div class="flex flex-col md:flex-row gap-6">
<div class="md:w-1/2">
<div class="card flex flex-col gap-2">
<h5>Default</h5>
<div class="flex flex-wrap gap-2">
<Button label="Submit"></Button>
<Button label="Disabled" :disabled="true"></Button>
<Button label="Link" class="p-button-link" />
</div>
</div>
<div class="card flex flex-col gap-2">
<h5>Severities</h5>
<div class="flex flex-wrap gap-2">
<Button label="Primary" />
<Button label="Secondary" severity="secondary" />
<Button label="Success" severity="success" />
<Button label="Info" severity="info" />
<Button label="Warn" severity="warn" />
<Button label="Help" severity="help" />
<Button label="Danger" severity="danger" />
<Button label="Contrast" severity="contrast" />
</div>
</div>
<div class="card flex flex-col gap-2">
<h5>Text</h5>
<div class="flex flex-wrap gap-2">
<Button label="Primary" text />
<Button label="Secondary" severity="secondary" text />
<Button label="Success" severity="success" text />
<Button label="Info" severity="info" text />
<Button label="Warn" severity="warn" text />
<Button label="Help" severity="help" text />
<Button label="Danger" severity="danger" text />
<Button label="Plain" plain text />
</div>
</div>
<div class="card flex flex-col gap-2">
<h5>Outlined</h5>
<div class="flex flex-wrap gap-2">
<Button label="Primary" outlined />
<Button label="Secondary" severity="secondary" outlined />
<Button label="Success" severity="success" outlined />
<Button label="Info" severity="info" outlined />
<Button label="warn" severity="warn" outlined />
<Button label="Help" severity="help" outlined />
<Button label="Danger" severity="danger" outlined />
<Button label="Contrast" severity="contrast" outlined />
</div>
</div>
<div class="card flex flex-col gap-2">
<h5>Button Group</h5>
<div class="flex flex-wrap gap-2">
<ButtonGroup>
<Button label="Save" icon="pi pi-check" />
<Button label="Delete" icon="pi pi-trash" />
<Button label="Cancel" icon="pi pi-times" />
</ButtonGroup>
</div>
</div>
<div class="card flex flex-col gap-2">
<h5>SplitButton</h5>
<div class="flex flex-wrap gap-2">
<SplitButton label="Save" :model="items"></SplitButton>
<SplitButton label="Save" :model="items" severity="secondary"></SplitButton>
<SplitButton label="Save" :model="items" severity="success"></SplitButton>
<SplitButton label="Save" :model="items" severity="info"></SplitButton>
<SplitButton label="Save" :model="items" severity="warn"></SplitButton>
<SplitButton label="Save" :model="items" severity="help"></SplitButton>
<SplitButton label="Save" :model="items" severity="danger"></SplitButton>
<SplitButton label="Save" :model="items" severity="contrast"></SplitButton>
</div>
</div>
<div class="card flex flex-col gap-2">
<h5>Templating</h5>
<div class="flex flex-wrap gap-2">
<Button type="button">
<img alt="logo" src="/demo/images/logo-white.svg" style="width: 1.5rem" />
</Button>
<Button type="button" outlined severity="success">
<img alt="logo" src="/demo/images/logo.svg" style="width: 1.5rem" />
<span class="ml-2 text-bold">PrimeVue</span>
</Button>
</div>
</div>
</div>
<div class="md:w-1/2">
<div class="card flex flex-col gap-2">
<h5>Icons</h5>
<div class="flex flex-wrap gap-2">
<Button icon="pi pi-star-fill" class="mr-2 mb-2"></Button>
<Button label="Bookmark" icon="pi pi-bookmark" class="mr-2 mb-2"></Button>
<Button label="Bookmark" icon="pi pi-bookmark" iconPos="right" class="mr-2 mb-2"></Button>
</div>
</div>
<div class="card flex flex-col gap-2">
<h5>Raised</h5>
<div class="flex flex-wrap gap-2">
<Button label="Primary" raised />
<Button label="Secondary" severity="secondary" raised />
<Button label="Success" severity="success" raised />
<Button label="Info" severity="info" raised />
<Button label="Warn" severity="warn" raised />
<Button label="Help" severity="help" raised />
<Button label="Danger" severity="danger" raised />
<Button label="Contrast" severity="contrast" raised />
</div>
</div>
<div class="card flex flex-col gap-2">
<h5>Rounded</h5>
<div class="flex flex-wrap gap-2">
<Button label="Primary" rounded />
<Button label="Secondary" severity="secondary" rounded />
<Button label="Success" severity="success" rounded />
<Button label="Info" severity="info" rounded />
<Button label="Warn" severity="warn" rounded />
<Button label="Help" severity="help" rounded />
<Button label="Danger" severity="danger" rounded />
<Button label="Contrast" severity="contrast" rounded />
</div>
</div>
<div class="card flex flex-col gap-2">
<h5>Rounded Icons</h5>
<div class="flex flex-wrap gap-2">
<Button icon="pi pi-check" rounded />
<Button icon="pi pi-bookmark" severity="secondary" rounded />
<Button icon="pi pi-search" severity="success" rounded />
<Button icon="pi pi-user" severity="info" rounded />
<Button icon="pi pi-bell" severity="warn" rounded />
<Button icon="pi pi-heart" severity="help" rounded />
<Button icon="pi pi-times" severity="danger" rounded />
</div>
</div>
<div class="card flex flex-col gap-2">
<h5>Rounded Text</h5>
<div class="flex flex-wrap gap-2">
<Button icon="pi pi-check" text raised rounded />
<Button icon="pi pi-bookmark" severity="secondary" text raised rounded />
<Button icon="pi pi-search" severity="success" text raised rounded />
<Button icon="pi pi-user" severity="info" text raised rounded />
<Button icon="pi pi-bell" severity="warn" text raised rounded />
<Button icon="pi pi-heart" severity="help" text raised rounded />
<Button icon="pi pi-times" severity="danger" text raised rounded />
</div>
</div>
<div class="card flex flex-col gap-2">
<h5>Rounded Outlined</h5>
<div class="flex flex-wrap gap-2">
<Button icon="pi pi-check" rounded outlined />
<Button icon="pi pi-bookmark" severity="secondary" rounded outlined />
<Button icon="pi pi-search" severity="success" rounded outlined />
<Button icon="pi pi-user" severity="info" rounded outlined />
<Button icon="pi pi-bell" severity="warn" rounded outlined />
<Button icon="pi pi-heart" severity="help" rounded outlined />
<Button icon="pi pi-times" severity="danger" rounded outlined />
</div>
</div>
<div class="card flex flex-col gap-2">
<h5>Loading</h5>
<div class="flex flex-wrap gap-2">
<Button type="button" class="mr-2 mb-2" label="Search" icon="pi pi-search" :loading="loading[0]" @click="load(0)" />
<Button type="button" class="mr-2 mb-2" label="Search" icon="pi pi-search" iconPos="right" :loading="loading[1]" @click="load(1)" />
<Button type="button" class="mr-2 mb-2" icon="pi pi-search" :loading="loading[2]" @click="load(2)" />
<Button type="button" class="mr-2 mb-2" label="Search" :loading="loading[3]" @click="load(3)" />
</div>
</div>
</div>
</div>
</template>

View File

@@ -0,0 +1,283 @@
<script setup>
import { useLayout } from '@/layout/composables/layout';
import { ref, watch } from 'vue';
const { layoutConfig } = useLayout();
let documentStyle = getComputedStyle(document.documentElement);
let textColor = documentStyle.getPropertyValue('--text-color');
let textColorSecondary = documentStyle.getPropertyValue('--text-color-secondary');
let surfaceBorder = documentStyle.getPropertyValue('--surface-border');
const lineData = ref(null);
const pieData = ref(null);
const polarData = ref(null);
const barData = ref(null);
const radarData = ref(null);
const lineOptions = ref(null);
const pieOptions = ref(null);
const polarOptions = ref(null);
const barOptions = ref(null);
const radarOptions = ref(null);
const setColorOptions = () => {
documentStyle = getComputedStyle(document.documentElement);
textColor = documentStyle.getPropertyValue('--text-color');
textColorSecondary = documentStyle.getPropertyValue('--text-color-secondary');
surfaceBorder = documentStyle.getPropertyValue('--surface-border');
};
const setChart = () => {
barData.value = {
labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'],
datasets: [
{
label: 'My First dataset',
backgroundColor: documentStyle.getPropertyValue('--p-primary-500'),
borderColor: documentStyle.getPropertyValue('--p-primary-500'),
data: [65, 59, 80, 81, 56, 55, 40]
},
{
label: 'My Second dataset',
backgroundColor: documentStyle.getPropertyValue('--p-primary-200'),
borderColor: documentStyle.getPropertyValue('--p-primary-200'),
data: [28, 48, 40, 19, 86, 27, 90]
}
]
};
barOptions.value = {
plugins: {
legend: {
labels: {
fontColor: textColor
}
}
},
scales: {
x: {
ticks: {
color: textColorSecondary,
font: {
weight: 500
}
},
grid: {
display: false,
drawBorder: false
}
},
y: {
ticks: {
color: textColorSecondary
},
grid: {
color: surfaceBorder,
drawBorder: false
}
}
}
};
pieData.value = {
labels: ['A', 'B', 'C'],
datasets: [
{
data: [540, 325, 702],
backgroundColor: [documentStyle.getPropertyValue('--p-indigo-500'), documentStyle.getPropertyValue('--p-purple-500'), documentStyle.getPropertyValue('--p-teal-500')],
hoverBackgroundColor: [documentStyle.getPropertyValue('--p-indigo-400'), documentStyle.getPropertyValue('--p-purple-400'), documentStyle.getPropertyValue('--p-teal-400')]
}
]
};
pieOptions.value = {
plugins: {
legend: {
labels: {
usePointStyle: true,
color: textColor
}
}
}
};
lineData.value = {
labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'],
datasets: [
{
label: 'First Dataset',
data: [65, 59, 80, 81, 56, 55, 40],
fill: false,
backgroundColor: documentStyle.getPropertyValue('--p-primary-500'),
borderColor: documentStyle.getPropertyValue('--p-primary-500'),
tension: 0.4
},
{
label: 'Second Dataset',
data: [28, 48, 40, 19, 86, 27, 90],
fill: false,
backgroundColor: documentStyle.getPropertyValue('--p-primary-200'),
borderColor: documentStyle.getPropertyValue('--p-primary-200'),
tension: 0.4
}
]
};
lineOptions.value = {
plugins: {
legend: {
labels: {
fontColor: textColor
}
}
},
scales: {
x: {
ticks: {
color: textColorSecondary
},
grid: {
color: surfaceBorder,
drawBorder: false
}
},
y: {
ticks: {
color: textColorSecondary
},
grid: {
color: surfaceBorder,
drawBorder: false
}
}
}
};
polarData.value = {
datasets: [
{
data: [11, 16, 7, 3],
backgroundColor: [documentStyle.getPropertyValue('--p-indigo-500'), documentStyle.getPropertyValue('--p-purple-500'), documentStyle.getPropertyValue('--p-teal-500'), documentStyle.getPropertyValue('--p-orange-500')],
label: 'My dataset'
}
],
labels: ['Indigo', 'Purple', 'Teal', 'Orange']
};
polarOptions.value = {
plugins: {
legend: {
labels: {
color: textColor
}
}
},
scales: {
r: {
grid: {
color: surfaceBorder
}
}
}
};
radarData.value = {
labels: ['Eating', 'Drinking', 'Sleeping', 'Designing', 'Coding', 'Cycling', 'Running'],
datasets: [
{
label: 'My First dataset',
borderColor: documentStyle.getPropertyValue('--p-indigo-400'),
pointBackgroundColor: documentStyle.getPropertyValue('--p-indigo-400'),
pointBorderColor: documentStyle.getPropertyValue('--p-indigo-400'),
pointHoverBackgroundColor: textColor,
pointHoverBorderColor: documentStyle.getPropertyValue('--p-indigo-400'),
data: [65, 59, 90, 81, 56, 55, 40]
},
{
label: 'My Second dataset',
borderColor: documentStyle.getPropertyValue('--p-purple-400'),
pointBackgroundColor: documentStyle.getPropertyValue('--p-purple-400'),
pointBorderColor: documentStyle.getPropertyValue('--p-purple-400'),
pointHoverBackgroundColor: textColor,
pointHoverBorderColor: documentStyle.getPropertyValue('--p-purple-400'),
data: [28, 48, 40, 19, 96, 27, 100]
}
]
};
radarOptions.value = {
plugins: {
legend: {
labels: {
fontColor: textColor
}
}
},
scales: {
r: {
grid: {
color: textColorSecondary
}
}
}
};
};
watch(
layoutConfig.primary,
() => {
setColorOptions();
setChart();
},
{ immediate: true }
);
watch(
layoutConfig.darkTheme,
() => {
setColorOptions();
setChart();
},
{ immediate: true }
);
</script>
<template>
<Fluid class="grid grid-cols-12 gap-4">
<div class="col-span-12 xl:col-span-6">
<div class="card">
<h5>Linear Chart</h5>
<Chart type="line" :data="lineData" :options="lineOptions"></Chart>
</div>
</div>
<div class="col-span-12 xl:col-span-6">
<div class="card">
<h5>Bar Chart</h5>
<Chart type="bar" :data="barData" :options="barOptions"></Chart>
</div>
</div>
<div class="col-span-12 xl:col-span-6">
<div class="card flex flex-col items-center">
<h5 class="text-left w-full">Pie Chart</h5>
<Chart type="pie" :data="pieData" :options="pieOptions"></Chart>
</div>
</div>
<div class="col-span-12 xl:col-span-6">
<div class="card flex flex-col items-center">
<h5 class="text-left w-full">Doughnut Chart</h5>
<Chart type="doughnut" :data="pieData" :options="pieOptions"></Chart>
</div>
</div>
<div class="col-span-12 xl:col-span-6">
<div class="card flex flex-col items-center">
<h5 class="text-left w-full">Polar Area Chart</h5>
<Chart type="polarArea" :data="polarData" :options="polarOptions"></Chart>
</div>
</div>
<div class="col-span-12 xl:col-span-6">
<div class="card flex flex-col items-center">
<h5 class="text-left w-full">Radar Chart</h5>
<Chart type="radar" :data="radarData" :options="radarOptions"></Chart>
</div>
</div>
</Fluid>
</template>

View File

@@ -0,0 +1,34 @@
<script setup>
import { ref } from 'vue';
import { useToast } from 'primevue/usetoast';
const toast = useToast();
const fileupload = ref();
const upload = () => {
fileupload.value.upload();
};
const onUpload = () => {
toast.add({ severity: 'info', summary: 'Success', detail: 'File Uploaded', life: 3000 });
};
</script>
<template>
<div class="grid grid-cols-12 gap-4">
<div class="col-span-12">
<div class="card">
<h5>Advanced</h5>
<FileUpload name="demo[]" @uploader="onUpload" :multiple="true" accept="image/*" :maxFileSize="1000000" customUpload />
</div>
<div class="card">
<h5>Basic</h5>
<div class="card flex flex-col gap-6 items-center justify-center">
<Toast />
<FileUpload ref="fileupload" mode="basic" name="demo[]" url="/api/upload" accept="image/*" :maxFileSize="1000000" @upload="onUpload" />
<Button label="Upload" @click="upload" severity="secondary" />
</div>
</div>
</div>
</div>
</template>

View File

@@ -0,0 +1,121 @@
<script setup>
import { ref } from 'vue';
const dropdownItems = ref([
{ name: 'Option 1', code: 'Option 1' },
{ name: 'Option 2', code: 'Option 2' },
{ name: 'Option 3', code: 'Option 3' }
]);
const dropdownItem = ref(null);
</script>
<template>
<Fluid>
<div class="flex flex-col md:flex-row gap-6">
<div class="md:w-1/2">
<div class="card flex flex-col gap-4">
<h5>Vertical</h5>
<div class="flex flex-col gap-2">
<label for="name1">Name</label>
<InputText id="name1" type="text" />
</div>
<div class="flex flex-col gap-2">
<label for="email1">Email</label>
<InputText id="email1" type="text" />
</div>
<div class="flex flex-col gap-2">
<label for="age1">Age</label>
<InputText id="age1" type="text" />
</div>
</div>
<div class="card flex flex-col gap-4">
<h5>Vertical Grid</h5>
<div class="flex flex-wrap gap-4">
<div class="flex flex-col grow basis-0 gap-2">
<label for="name2">Name</label>
<InputText id="name2" type="text" />
</div>
<div class="flex flex-col grow basis-0 gap-2">
<label for="email2">Email</label>
<InputText id="email2" type="text" />
</div>
</div>
</div>
</div>
<div class="md:w-1/2">
<div class="card flex flex-col gap-4">
<h5>Horizontal</h5>
<div class="grid grid-cols-12 gap-2">
<label for="name3" class="flex items-center col-span-12 mb-2 md:col-span-2 md:mb-0">Name</label>
<div class="col-span-12 md:col-span-10">
<InputText id="name3" type="text" />
</div>
</div>
<div class="grid grid-cols-12 gap-2">
<label for="email3" class="flex items-center col-span-12 mb-2 md:col-span-2 md:mb-0">Email</label>
<div class="col-span-12 md:col-span-10">
<InputText id="email3" type="text" />
</div>
</div>
</div>
<div class="card flex flex-col gap-4">
<h5>Inline</h5>
<div class="flex flex-wrap items-start gap-4">
<div class="field">
<label for="firstname1" class="sr-only">Firstname</label>
<InputText id="firstname1" type="text" placeholder="Firstname" />
</div>
<div class="field">
<label for="lastname1" class="sr-only">Lastname</label>
<InputText id="lastname1" type="text" placeholder="Lastname" />
</div>
<Button label="Submit" :fluid="false"></Button>
</div>
</div>
<div class="card flex flex-col gap-4">
<h5>Help Text</h5>
<div class="flex flex-wrap gap-2">
<label for="username">Username</label>
<InputText id="username" type="text" />
<small>Enter your username to reset your password.</small>
</div>
</div>
</div>
</div>
<div class="flex mt-6">
<div class="card flex flex-col gap-4 w-full">
<h5>Advanced</h5>
<div class="flex flex-col md:flex-row gap-4">
<div class="flex flex-wrap gap-2 w-full">
<label for="firstname2">Firstname</label>
<InputText id="firstname2" type="text" />
</div>
<div class="flex flex-wrap gap-2 w-full">
<label for="lastname2">Lastname</label>
<InputText id="lastname2" type="text" />
</div>
</div>
<div class="flex flex-wrap">
<label for="address">Address</label>
<Textarea id="address" rows="4" />
</div>
<div class="flex flex-col md:flex-row gap-4">
<div class="flex flex-wrap gap-2 w-full">
<label for="state">State</label>
<Select id="state" v-model="dropdownItem" :options="dropdownItems" optionLabel="name" placeholder="Select One" class="w-full"></Select>
</div>
<div class="flex flex-wrap gap-2 w-full">
<label for="zip">Zip</label>
<InputText id="zip" type="text" />
</div>
</div>
</div>
</div>
</Fluid>
</template>

View File

@@ -0,0 +1,257 @@
<script setup>
import { CountryService } from '@/service/CountryService';
import { NodeService } from '@/service/NodeService';
import { onMounted, ref } from 'vue';
const floatValue = ref(null);
const autoValue = ref(null);
const selectedAutoValue = ref(null);
const autoFilteredValue = ref([]);
const calendarValue = ref(null);
const inputNumberValue = ref(null);
const chipsValue = ref(null);
const sliderValue = ref(50);
const ratingValue = ref(null);
const colorValue = ref('#1976D2');
const radioValue = ref(null);
const checkboxValue = ref([]);
const switchValue = ref(false);
const listboxValues = ref([
{ name: 'New York', code: 'NY' },
{ name: 'Rome', code: 'RM' },
{ name: 'London', code: 'LDN' },
{ name: 'Istanbul', code: 'IST' },
{ name: 'Paris', code: 'PRS' }
]);
const listboxValue = ref(null);
const dropdownValues = ref([
{ name: 'New York', code: 'NY' },
{ name: 'Rome', code: 'RM' },
{ name: 'London', code: 'LDN' },
{ name: 'Istanbul', code: 'IST' },
{ name: 'Paris', code: 'PRS' }
]);
const dropdownValue = ref(null);
const multiselectValues = ref([
{ name: 'Australia', code: 'AU' },
{ name: 'Brazil', code: 'BR' },
{ name: 'China', code: 'CN' },
{ name: 'Egypt', code: 'EG' },
{ name: 'France', code: 'FR' },
{ name: 'Germany', code: 'DE' },
{ name: 'India', code: 'IN' },
{ name: 'Japan', code: 'JP' },
{ name: 'Spain', code: 'ES' },
{ name: 'United States', code: 'US' }
]);
const multiselectValue = ref(null);
const toggleValue = ref(false);
const selectButtonValue1 = ref(null);
const selectButtonValues1 = ref([{ name: 'Option 1' }, { name: 'Option 2' }, { name: 'Option 3' }]);
const selectButtonValue2 = ref(null);
const selectButtonValues2 = ref([{ name: 'Option 1' }, { name: 'Option 2' }, { name: 'Option 3' }]);
const knobValue = ref(50);
const inputGroupValue = ref(false);
const treeSelectNodes = ref(null);
const selectedNode = ref(null);
onMounted(() => {
CountryService.getCountries().then((data) => (autoValue.value = data));
NodeService.getTreeNodes().then((data) => (treeSelectNodes.value = data));
});
const searchCountry = (event) => {
setTimeout(() => {
if (!event.query.trim().length) {
autoFilteredValue.value = [...autoValue.value];
} else {
autoFilteredValue.value = autoValue.value.filter((country) => {
return country.name.toLowerCase().startsWith(event.query.toLowerCase());
});
}
}, 250);
};
</script>
<template>
<Fluid class="flex flex-col md:flex-row gap-6">
<div class="md:w-1/2">
<div class="card flex flex-col gap-4">
<div class="font-semibold text-xl mb-4">InputText</div>
<div class="flex flex-col md:flex-row gap-4">
<InputText type="text" placeholder="Default" />
<InputText type="text" placeholder="Disabled" :disabled="true" />
<InputText type="text" placeholder="Invalid" invalid />
</div>
<h5 class="mt-6">Icons</h5>
<IconField>
<InputIcon class="pi pi-user" />
<InputText type="text" placeholder="Username" />
</IconField>
<IconField iconPosition="left">
<InputText type="text" placeholder="Search" />
<InputIcon class="pi pi-search" />
</IconField>
<h5 class="mt-6">Float Label</h5>
<FloatLabel>
<InputText id="username" type="text" v-model="floatValue" />
<label for="username">Username</label>
</FloatLabel>
<h5 class="mt-6">Textarea</h5>
<Textarea placeholder="Your Message" :autoResize="true" rows="3" cols="30" />
<h5 class="mt-6">AutoComplete</h5>
<AutoComplete placeholder="Search" id="dd" :dropdown="true" :multiple="true" v-model="selectedAutoValue" :suggestions="autoFilteredValue" @complete="searchCountry($event)" field="name" />
<h5 class="mt-6">DatePicker</h5>
<DatePicker :showIcon="true" :showButtonBar="true" v-model="calendarValue"></DatePicker>
<h5 class="mt-6">Spinner</h5>
<InputNumber v-model="inputNumberValue" showButtons mode="decimal"></InputNumber>
<h5 class="mt-6">Chips</h5>
<AutoComplete v-model="chipsValue" :typeahead="false" multiple />
</div>
<div class="card flex flex-col gap-4">
<h5>Slider</h5>
<InputText v-model.number="sliderValue" />
<Slider v-model="sliderValue" />
<div class="flex flex-row mt-6">
<div class="flex flex-col gap-4 w-1/2">
<h5>Rating</h5>
<Rating v-model="ratingValue" />
</div>
<div class="flex flex-col gap-4 w-1/2">
<h5>ColorPicker</h5>
<ColorPicker style="width: 2rem" v-model="colorValue" />
</div>
</div>
<h5 class="mt-6">Knob</h5>
<Knob v-model="knobValue" :step="10" :min="-50" :max="50" valueTemplate="{value}%" />
</div>
</div>
<div class="md:w-1/2">
<div class="card flex flex-col gap-4">
<h5>RadioButton</h5>
<div class="flex flex-col md:flex-row gap-4">
<div class="flex items-center">
<RadioButton id="option1" name="option" value="Chicago" v-model="radioValue" />
<label for="option1" class="leading-none ml-2">Chicago</label>
</div>
<div class="flex items-center">
<RadioButton id="option2" name="option" value="Los Angeles" v-model="radioValue" />
<label for="option2" class="leading-none ml-2">Los Angeles</label>
</div>
<div class="flex items-center">
<RadioButton id="option3" name="option" value="New York" v-model="radioValue" />
<label for="option3" class="leading-none ml-2">New York</label>
</div>
</div>
<h5 class="mt-6">Checkbox</h5>
<div class="flex flex-col md:flex-row gap-4">
<div class="flex items-center">
<Checkbox id="checkOption1" name="option" value="Chicago" v-model="checkboxValue" />
<label for="checkOption1" class="ml-2">Chicago</label>
</div>
<div class="flex items-center">
<Checkbox id="checkOption2" name="option" value="Los Angeles" v-model="checkboxValue" />
<label for="checkOption2" class="ml-2">Los Angeles</label>
</div>
<div class="flex items-center">
<Checkbox id="checkOption3" name="option" value="New York" v-model="checkboxValue" />
<label for="checkOption3" class="ml-2">New York</label>
</div>
</div>
<h5 class="mt-6">Input Switch</h5>
<ToggleSwitch v-model="switchValue" />
</div>
<div class="card flex flex-col gap-4">
<h5>Listbox</h5>
<Listbox v-model="listboxValue" :options="listboxValues" optionLabel="name" :filter="true" />
<h5 class="mt-6">Select</h5>
<Select v-model="dropdownValue" :options="dropdownValues" optionLabel="name" placeholder="Select" />
<h5 class="mt-6">MultiSelect</h5>
<MultiSelect v-model="multiselectValue" :options="multiselectValues" optionLabel="name" placeholder="Select Countries" :filter="true">
<template #value="slotProps">
<div class="inline-flex items-center py-1 px-2 bg-primary text-primary-contrast rounded-border mr-2" v-for="option of slotProps.value" :key="option.code">
<span :class="'mr-2 flag flag-' + option.code.toLowerCase()" style="width: 18px; height: 12px" />
<div>{{ option.name }}</div>
</div>
<template v-if="!slotProps.value || slotProps.value.length === 0">
<div class="p-1">Select Countries</div>
</template>
</template>
<template #option="slotProps">
<div class="flex items-center">
<span :class="'mr-2 flag flag-' + slotProps.option.code.toLowerCase()" style="width: 18px; height: 12px" />
<div>{{ slotProps.option.name }}</div>
</div>
</template>
</MultiSelect>
<h5 class="mt-6">TreeSelect</h5>
<TreeSelect v-model="selectedNode" :options="treeSelectNodes" placeholder="Select Item"></TreeSelect>
</div>
<div class="card flex flex-col gap-4">
<h5>ToggleButton</h5>
<ToggleButton v-model="toggleValue" onLabel="Yes" offLabel="No" :style="{ width: '10em' }" />
<h5 class="mt-6">SelectButton</h5>
<SelectButton v-model="selectButtonValue1" :options="selectButtonValues1" optionLabel="name" />
<h5 class="mt-6">SelectButton - Multiple</h5>
<SelectButton v-model="selectButtonValue2" :options="selectButtonValues2" optionLabel="name" :multiple="true" />
</div>
</div>
</Fluid>
<Fluid class="flex mt-6">
<div class="card flex flex-col gap-4 w-full">
<h5>Input Groups</h5>
<div class="flex flex-col md:flex-row gap-4">
<InputGroup>
<InputGroupAddon>
<i class="pi pi-user"></i>
</InputGroupAddon>
<InputText placeholder="Username" />
</InputGroup>
<InputGroup>
<InputGroupAddon>
<i class="pi pi-clock"></i>
</InputGroupAddon>
<InputGroupAddon>
<i class="pi pi-star-fill"></i>
</InputGroupAddon>
<InputNumber placeholder="Price" />
<InputGroupAddon>$</InputGroupAddon>
<InputGroupAddon>.00</InputGroupAddon>
</InputGroup>
</div>
<div class="flex flex-col md:flex-row gap-4">
<InputGroup>
<Button label="Search" />
<InputText placeholder="Keyword" />
</InputGroup>
<InputGroup>
<InputGroupAddon>
<Checkbox v-model="inputGroupValue" :binary="true" />
</InputGroupAddon>
<InputText placeholder="Confirm" />
</InputGroup>
</div>
</div>
</Fluid>
</template>

182
src/views/uikit/ListDoc.vue Normal file
View File

@@ -0,0 +1,182 @@
<script setup>
import { ref, onMounted } from 'vue';
import { ProductService } from '@/service/ProductService';
const picklistValue = ref([
[
{ name: 'San Francisco', code: 'SF' },
{ name: 'London', code: 'LDN' },
{ name: 'Paris', code: 'PRS' },
{ name: 'Istanbul', code: 'IST' },
{ name: 'Berlin', code: 'BRL' },
{ name: 'Barcelona', code: 'BRC' },
{ name: 'Rome', code: 'RM' }
],
[]
]);
const orderlistValue = ref([
{ name: 'San Francisco', code: 'SF' },
{ name: 'London', code: 'LDN' },
{ name: 'Paris', code: 'PRS' },
{ name: 'Istanbul', code: 'IST' },
{ name: 'Berlin', code: 'BRL' },
{ name: 'Barcelona', code: 'BRC' },
{ name: 'Rome', code: 'RM' }
]);
const products = ref(null);
const options = ref(['list', 'grid']);
const layout = ref('grid');
onMounted(() => {
ProductService.getProductsSmall().then((data) => (products.value = data));
});
const getSeverity = (product) => {
switch (product.inventoryStatus) {
case 'INSTOCK':
return 'success';
case 'LOWSTOCK':
return 'warning';
case 'OUTOFSTOCK':
return 'danger';
default:
return null;
}
};
</script>
<template>
<div class="flex flex-col gap-6">
<div class="card">
<h5>DataView</h5>
<DataView :value="products" :layout="layout">
<template #header>
<div class="flex justify-end">
<SelectButton v-model="layout" :options="options" :allowEmpty="false">
<template #option="{ option }">
<i :class="[option === 'list' ? 'pi pi-bars' : 'pi pi-table']" />
</template>
</SelectButton>
</div>
</template>
<template #list="slotProps">
<div class="flex flex-col">
<div v-for="(item, index) in slotProps.items" :key="index">
<div class="flex flex-col sm:flex-row sm:items-center p-6 gap-4" :class="{ 'border-t border-surface-200 dark:border-surface-700': index !== 0 }">
<div class="md:w-40 relative">
<img class="block xl:block mx-auto rounded w-full" :src="`https://primefaces.org/cdn/primevue/images/product/${item.image}`" :alt="item.name" />
<Tag :value="item.inventoryStatus" :severity="getSeverity(item)" class="absolute dark:!bg-surface-900" style="left: 4px; top: 4px"></Tag>
</div>
<div class="flex flex-col md:flex-row justify-between md:items-center flex-1 gap-6">
<div class="flex flex-row md:flex-col justify-between items-start gap-2">
<div>
<span class="font-medium text-surface-500 dark:text-surface-400 text-sm">{{ item.category }}</span>
<div class="text-lg font-medium mt-2">{{ item.name }}</div>
</div>
<div class="bg-surface-100 p-1" style="border-radius: 30px">
<div
class="bg-surface-0 flex items-center gap-2 justify-center py-1 px-2"
style="
border-radius: 30px;
box-shadow:
0px 1px 2px 0px rgba(0, 0, 0, 0.04),
0px 1px 2px 0px rgba(0, 0, 0, 0.06);
"
>
<span class="text-surface-900 font-medium text-sm">{{ item.rating }}</span>
<i class="pi pi-star-fill text-yellow-500"></i>
</div>
</div>
</div>
<div class="flex flex-col md:items-end gap-8">
<span class="text-xl font-semibold">${{ item.price }}</span>
<div class="flex flex-row-reverse md:flex-row gap-2">
<Button icon="pi pi-heart" outlined></Button>
<Button icon="pi pi-shopping-cart" label="Buy Now" :disabled="item.inventoryStatus === 'OUTOFSTOCK'" class="flex-auto md:flex-initial whitespace-nowrap"></Button>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<template #grid="slotProps">
<div class="grid grid-cols-12 gap-4">
<div v-for="(item, index) in slotProps.items" :key="index" class="col-span-12 sm:col-span-6 md:col-span-4 xl:col-span-6 p-2">
<div class="p-6 border border-surface-200 dark:border-surface-700 bg-surface-0 dark:bg-surface-900 rounded flex flex-col">
<div class="bg-surface-50 flex justify-center rounded p-4">
<div class="relative mx-auto">
<img class="rounded w-full" :src="`https://primefaces.org/cdn/primevue/images/product/${item.image}`" :alt="item.name" style="max-width: 300px" />
<Tag :value="item.inventoryStatus" :severity="getSeverity(item)" class="absolute dark:!bg-surface-900" style="left: 4px; top: 4px"></Tag>
</div>
</div>
<div class="pt-6">
<div class="flex flex-row justify-between items-start gap-2">
<div>
<span class="font-medium text-surface-500 dark:text-surface-400 text-sm">{{ item.category }}</span>
<div class="text-lg font-medium mt-1">{{ item.name }}</div>
</div>
<div class="bg-surface-100 p-1" style="border-radius: 30px">
<div
class="bg-surface-0 flex items-center gap-2 justify-center py-1 px-2"
style="
border-radius: 30px;
box-shadow:
0px 1px 2px 0px rgba(0, 0, 0, 0.04),
0px 1px 2px 0px rgba(0, 0, 0, 0.06);
"
>
<span class="text-surface-900 font-medium text-sm">{{ item.rating }}</span>
<i class="pi pi-star-fill text-yellow-500"></i>
</div>
</div>
</div>
<div class="flex flex-col gap-6 mt-6">
<span class="text-2xl font-semibold">${{ item.price }}</span>
<div class="flex gap-2">
<Button icon="pi pi-shopping-cart" label="Buy Now" :disabled="item.inventoryStatus === 'OUTOFSTOCK'" class="flex-auto whitespace-nowrap"></Button>
<Button icon="pi pi-heart" outlined></Button>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
</DataView>
</div>
<div class="flex flex-col lg:flex-row gap-4">
<div class="lg:w-2/3">
<div class="card">
<h5>PickList</h5>
<PickList v-model="picklistValue" breakpoint="1400px" dataKey="id">
<template #option="{ option }">
{{ option.name }}
</template>
</PickList>
</div>
</div>
<div class="lg:w-1/3">
<div class="card">
<h5>OrderList</h5>
<div class="lg:flex lg:justify-center">
<OrderList v-model="orderlistValue" breakpoint="1400px" dataKey="id" pt:pcList:root="w-full">
<template #option="{ option }">
{{ option.name }}
</template>
</OrderList>
</div>
</div>
</div>
</div>
</div>
</template>

View File

@@ -0,0 +1,109 @@
<script setup>
import { ProductService } from '@/service/ProductService';
import { PhotoService } from '@/service/PhotoService';
import { ref, onMounted } from 'vue';
const products = ref([]);
const images = ref([]);
const galleriaResponsiveOptions = ref([
{
breakpoint: '1024px',
numVisible: 5
},
{
breakpoint: '960px',
numVisible: 4
},
{
breakpoint: '768px',
numVisible: 3
},
{
breakpoint: '560px',
numVisible: 1
}
]);
const carouselResponsiveOptions = ref([
{
breakpoint: '1024px',
numVisible: 3,
numScroll: 3
},
{
breakpoint: '768px',
numVisible: 2,
numScroll: 2
},
{
breakpoint: '560px',
numVisible: 1,
numScroll: 1
}
]);
onMounted(() => {
ProductService.getProductsSmall().then((data) => (products.value = data));
PhotoService.getImages().then((data) => (images.value = data));
});
const getSeverity = (status) => {
switch (status) {
case 'INSTOCK':
return 'success';
case 'LOWSTOCK':
return 'warning';
case 'OUTOFSTOCK':
return 'danger';
default:
return null;
}
};
</script>
<template>
<div class="card">
<h5>Carousel</h5>
<Carousel :value="products" :numVisible="3" :numScroll="3" :responsiveOptions="carouselResponsiveOptions">
<template #item="slotProps">
<div class="border border-surface-200 dark:border-surface-700 rounded m-2 p-4">
<div class="mb-4">
<div class="relative mx-auto">
<img :src="'https://primefaces.org/cdn/primevue/images/product/' + slotProps.data.image" :alt="slotProps.data.name" class="w-full rounded" />
<Tag :value="slotProps.data.inventoryStatus" :severity="getSeverity(slotProps.data.inventoryStatus)" class="absolute" style="left: 5px; top: 5px" />
</div>
</div>
<div class="mb-4 font-medium">{{ slotProps.data.name }}</div>
<div class="flex justify-between items-center">
<div class="mt-0 font-semibold text-xl">${{ slotProps.data.price }}</div>
<span>
<Button icon="pi pi-heart" severity="secondary" outlined />
<Button icon="pi pi-shopping-cart" class="ml-2" />
</span>
</div>
</div>
</template>
</Carousel>
</div>
<div class="card">
<h5>Image</h5>
<div class="flex justify-center">
<Image src="https://primefaces.org/cdn/primevue/images/galleria/galleria10.jpg" alt="Image" width="250" />
</div>
</div>
<div class="card">
<h5>Galleria</h5>
<Galleria :value="images" :responsiveOptions="galleriaResponsiveOptions" :numVisible="5" containerStyle="max-width: 640px">
<template #item="slotProps">
<img :src="slotProps.item.itemImageSrc" :alt="slotProps.item.alt" style="width: 100%" />
</template>
<template #thumbnail="slotProps">
<img :src="slotProps.item.thumbnailImageSrc" :alt="slotProps.item.alt" />
</template>
</Galleria>
</div>
</template>

564
src/views/uikit/MenuDoc.vue Normal file
View File

@@ -0,0 +1,564 @@
<script setup>
import { ref } from 'vue';
const menu = ref(null);
const contextMenu = ref(null);
const nestedMenuitems = ref([
{
label: 'Customers',
icon: 'pi pi-fw pi-table',
items: [
{
label: 'New',
icon: 'pi pi-fw pi-user-plus',
items: [
{
label: 'Customer',
icon: 'pi pi-fw pi-plus'
},
{
label: 'Duplicate',
icon: 'pi pi-fw pi-copy'
}
]
},
{
label: 'Edit',
icon: 'pi pi-fw pi-user-edit'
}
]
},
{
label: 'Orders',
icon: 'pi pi-fw pi-shopping-cart',
items: [
{
label: 'View',
icon: 'pi pi-fw pi-list'
},
{
label: 'Search',
icon: 'pi pi-fw pi-search'
}
]
},
{
label: 'Shipments',
icon: 'pi pi-fw pi-envelope',
items: [
{
label: 'Tracker',
icon: 'pi pi-fw pi-compass'
},
{
label: 'Map',
icon: 'pi pi-fw pi-map-marker'
},
{
label: 'Manage',
icon: 'pi pi-fw pi-pencil'
}
]
},
{
label: 'Profile',
icon: 'pi pi-fw pi-user',
items: [
{
label: 'Settings',
icon: 'pi pi-fw pi-cog'
},
{
label: 'Billing',
icon: 'pi pi-fw pi-file'
}
]
},
{
label: 'Quit',
icon: 'pi pi-fw pi-sign-out'
}
]);
const breadcrumbHome = ref({ icon: 'pi pi-home', to: '/' });
const breadcrumbItems = ref([{ label: 'Computer' }, { label: 'Notebook' }, { label: 'Accessories' }, { label: 'Backpacks' }, { label: 'Item' }]);
const tieredMenuItems = ref([
{
label: 'Customers',
icon: 'pi pi-fw pi-table',
items: [
{
label: 'New',
icon: 'pi pi-fw pi-user-plus',
items: [
{
label: 'Customer',
icon: 'pi pi-fw pi-plus'
},
{
label: 'Duplicate',
icon: 'pi pi-fw pi-copy'
}
]
},
{
label: 'Edit',
icon: 'pi pi-fw pi-user-edit'
}
]
},
{
label: 'Orders',
icon: 'pi pi-fw pi-shopping-cart',
items: [
{
label: 'View',
icon: 'pi pi-fw pi-list'
},
{
label: 'Search',
icon: 'pi pi-fw pi-search'
}
]
},
{
label: 'Shipments',
icon: 'pi pi-fw pi-envelope',
items: [
{
label: 'Tracker',
icon: 'pi pi-fw pi-compass'
},
{
label: 'Map',
icon: 'pi pi-fw pi-map-marker'
},
{
label: 'Manage',
icon: 'pi pi-fw pi-pencil'
}
]
},
{
label: 'Profile',
icon: 'pi pi-fw pi-user',
items: [
{
label: 'Settings',
icon: 'pi pi-fw pi-cog'
},
{
label: 'Billing',
icon: 'pi pi-fw pi-file'
}
]
},
{
separator: true
},
{
label: 'Quit',
icon: 'pi pi-fw pi-sign-out'
}
]);
const overlayMenuItems = ref([
{
label: 'Save',
icon: 'pi pi-save'
},
{
label: 'Update',
icon: 'pi pi-refresh'
},
{
label: 'Delete',
icon: 'pi pi-trash'
},
{
separator: true
},
{
label: 'Home',
icon: 'pi pi-home'
}
]);
const menuitems = ref([
{
label: 'Customers',
items: [
{
label: 'New',
icon: 'pi pi-fw pi-plus'
},
{
label: 'Edit',
icon: 'pi pi-fw pi-user-edit'
}
]
},
{
label: 'Orders',
items: [
{
label: 'View',
icon: 'pi pi-fw pi-list'
},
{
label: 'Search',
icon: 'pi pi-fw pi-search'
}
]
}
]);
const contextMenuItems = ref([
{
label: 'Save',
icon: 'pi pi-save'
},
{
label: 'Update',
icon: 'pi pi-refresh'
},
{
label: 'Delete',
icon: 'pi pi-trash'
},
{
separator: true
},
{
label: 'Options',
icon: 'pi pi-cog'
}
]);
const megamenuItems = ref([
{
label: 'Fashion',
icon: 'pi pi-fw pi-tag',
items: [
[
{
label: 'Woman',
items: [{ label: 'Woman Item' }, { label: 'Woman Item' }, { label: 'Woman Item' }]
},
{
label: 'Men',
items: [{ label: 'Men Item' }, { label: 'Men Item' }, { label: 'Men Item' }]
}
],
[
{
label: 'Kids',
items: [{ label: 'Kids Item' }, { label: 'Kids Item' }]
},
{
label: 'Luggage',
items: [{ label: 'Luggage Item' }, { label: 'Luggage Item' }, { label: 'Luggage Item' }]
}
]
]
},
{
label: 'Electronics',
icon: 'pi pi-fw pi-desktop',
items: [
[
{
label: 'Computer',
items: [{ label: 'Computer Item' }, { label: 'Computer Item' }]
},
{
label: 'Camcorder',
items: [{ label: 'Camcorder Item' }, { label: 'Camcorder Item' }, { label: 'Camcorder Item' }]
}
],
[
{
label: 'TV',
items: [{ label: 'TV Item' }, { label: 'TV Item' }]
},
{
label: 'Audio',
items: [{ label: 'Audio Item' }, { label: 'Audio Item' }, { label: 'Audio Item' }]
}
],
[
{
label: 'Sports.7',
items: [{ label: 'Sports.7.1' }, { label: 'Sports.7.2' }]
}
]
]
},
{
label: 'Furniture',
icon: 'pi pi-fw pi-image',
items: [
[
{
label: 'Living Room',
items: [{ label: 'Living Room Item' }, { label: 'Living Room Item' }]
},
{
label: 'Kitchen',
items: [{ label: 'Kitchen Item' }, { label: 'Kitchen Item' }, { label: 'Kitchen Item' }]
}
],
[
{
label: 'Bedroom',
items: [{ label: 'Bedroom Item' }, { label: 'Bedroom Item' }]
},
{
label: 'Outdoor',
items: [{ label: 'Outdoor Item' }, { label: 'Outdoor Item' }, { label: 'Outdoor Item' }]
}
]
]
},
{
label: 'Sports',
icon: 'pi pi-fw pi-star',
items: [
[
{
label: 'Basketball',
items: [{ label: 'Basketball Item' }, { label: 'Basketball Item' }]
},
{
label: 'Football',
items: [{ label: 'Football Item' }, { label: 'Football Item' }, { label: 'Football Item' }]
}
],
[
{
label: 'Tennis',
items: [{ label: 'Tennis Item' }, { label: 'Tennis Item' }]
}
]
]
}
]);
const panelMenuitems = ref([
{
label: 'Customers',
icon: 'pi pi-fw pi-table',
items: [
{
label: 'New',
icon: 'pi pi-fw pi-user-plus',
items: [
{
label: 'Customer',
icon: 'pi pi-fw pi-plus'
},
{
label: 'Duplicate',
icon: 'pi pi-fw pi-copy'
}
]
},
{
label: 'Edit',
icon: 'pi pi-fw pi-user-edit'
}
]
},
{
label: 'Orders',
icon: 'pi pi-fw pi-shopping-cart',
items: [
{
label: 'View',
icon: 'pi pi-fw pi-list'
},
{
label: 'Search',
icon: 'pi pi-fw pi-search'
}
]
},
{
label: 'Shipments',
icon: 'pi pi-fw pi-envelope',
items: [
{
label: 'Tracker',
icon: 'pi pi-fw pi-compass'
},
{
label: 'Map',
icon: 'pi pi-fw pi-map-marker'
},
{
label: 'Manage',
icon: 'pi pi-fw pi-pencil'
}
]
},
{
label: 'Profile',
icon: 'pi pi-fw pi-user',
items: [
{
label: 'Settings',
icon: 'pi pi-fw pi-cog'
},
{
label: 'Billing',
icon: 'pi pi-fw pi-file'
}
]
}
]);
const toggleMenu = (event) => {
menu.value.toggle(event);
};
const onContextRightClick = (event) => {
contextMenu.value.show(event);
};
</script>
<template>
<div class="card">
<h5 class="mb-2">Menubar</h5>
<Menubar :model="nestedMenuitems">
<template #end>
<IconField iconPosition="left">
<InputIcon class="pi pi-search" />
<InputText type="text" placeholder="Search" />
</IconField>
</template>
</Menubar>
</div>
<div class="card">
<h5 class="mb-2">Breadcrumb</h5>
<Breadcrumb :home="breadcrumbHome" :model="breadcrumbItems" />
</div>
<div class="flex flex-col md:flex-row gap-4">
<div class="md:w-1/2">
<div class="card">
<h5 class="mb-2">Stepper</h5>
<Stepper value="1">
<StepList>
<Step value="1">Header I</Step>
<Step value="2">Header II</Step>
<Step value="3">Header III</Step>
</StepList>
<StepPanels>
<StepPanel v-slot="{ activateCallback }" value="1">
<div class="flex flex-col h-48">
<div class="border-2 border-dashed border-surface-200 dark:border-surface-700 rounded bg-surface-50 dark:bg-surface-950 flex-auto flex justify-center items-center font-medium">Content I</div>
</div>
<div class="flex pt-6 justify-end">
<Button label="Next" icon="pi pi-arrow-right" iconPos="right" @click="activateCallback('2')" />
</div>
</StepPanel>
<StepPanel v-slot="{ activateCallback }" value="2">
<div class="flex flex-col h-48">
<div class="border-2 border-dashed border-surface-200 dark:border-surface-700 rounded bg-surface-50 dark:bg-surface-950 flex-auto flex justify-center items-center font-medium">Content II</div>
</div>
<div class="flex pt-6 justify-between">
<Button label="Back" severity="secondary" icon="pi pi-arrow-left" @click="activateCallback('1')" />
<Button label="Next" icon="pi pi-arrow-right" iconPos="right" @click="activateCallback('3')" />
</div>
</StepPanel>
<StepPanel v-slot="{ activateCallback }" value="3">
<div class="flex flex-col h-48">
<div class="border-2 border-dashed border-surface-200 dark:border-surface-700 rounded bg-surface-50 dark:bg-surface-950 flex-auto flex justify-center items-center font-medium">Content III</div>
</div>
<div class="pt-6">
<Button label="Back" severity="secondary" icon="pi pi-arrow-left" @click="activateCallback('2')" />
</div>
</StepPanel>
</StepPanels>
</Stepper>
</div>
</div>
<div class="md:w-1/2">
<div class="card">
<h5 class="mb-2">Tabs</h5>
<Tabs value="0">
<TabList>
<Tab value="0">Header I</Tab>
<Tab value="1">Header II</Tab>
<Tab value="2">Header III</Tab>
</TabList>
<TabPanels>
<TabPanel value="0">
<p class="m-0">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea
commodo consequat. 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>
</TabPanel>
<TabPanel value="1">
<p class="m-0">
Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo.
Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Consectetur, adipisci velit, sed quia non numquam eius modi.
</p>
</TabPanel>
<TabPanel value="2">
<p class="m-0">
At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt
in culpa qui officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo
minus.
</p>
</TabPanel>
</TabPanels>
</Tabs>
</div>
</div>
</div>
<div class="flex flex-col md:flex-row gap-4 mt-6">
<div class="md:w-1/3">
<div class="card">
<h5 class="mb-2">Tiered Menu</h5>
<TieredMenu :model="tieredMenuItems" />
</div>
</div>
<div class="md:w-1/3">
<div class="card">
<h5 class="mb-2">Plain Menu</h5>
<Menu :model="menuitems" />
</div>
</div>
<div class="md:w-1/3">
<div class="card">
<h5 class="mb-2">Overlay Menu</h5>
<Menu ref="menu" :model="overlayMenuItems" :popup="true" />
<Button type="button" label="Options" icon="pi pi-angle-down" @click="toggleMenu" style="width: auto" />
</div>
<div class="card" @contextmenu="onContextRightClick">
<h5 class="mb-2">ContextMenu</h5>
Right click to display.
<ContextMenu ref="contextMenu" :model="contextMenuItems" />
</div>
</div>
</div>
<div class="flex flex-col md:flex-row gap-4 mt-6">
<div class="md:w-1/2">
<div class="card">
<h5 class="mb-2">MegaMenu - Horizontal</h5>
<MegaMenu :model="megamenuItems" />
<h5 class="mb-2 mt-8">MegaMenu - Vertical</h5>
<MegaMenu :model="megamenuItems" orientation="vertical" />
</div>
</div>
<div class="md:w-1/2">
<div class="card">
<h5 class="mb-2">PanelMenu</h5>
<PanelMenu :model="panelMenuitems" />
</div>
</div>
</div>
</template>

View File

@@ -0,0 +1,88 @@
<script setup>
import { ref } from 'vue';
import { useToast } from 'primevue/usetoast';
const toast = useToast();
const message = ref([]);
const username = ref(null);
const email = ref(null);
const value = ref(null);
const count = ref(0);
const addMessage = (type) => {
if (type === 'success') {
message.value = [{ severity: 'success', detail: 'Success Message', content: 'Message sent', id: count.value++ }];
} else if (type === 'info') {
message.value = [{ severity: 'info', detail: 'Info Message', content: 'PrimeVue rocks', id: count.value++ }];
} else if (type === 'warn') {
message.value = [{ severity: 'warn', detail: 'Warn Message', content: 'There are unsaved changes', id: count.value++ }];
} else if (type === 'error') {
message.value = [{ severity: 'error', detail: 'Error Message', content: 'Validation failed', id: count.value++ }];
}
};
const showSuccess = () => {
toast.add({ severity: 'success', summary: 'Success Message', detail: 'Message Detail', life: 3000 });
};
const showInfo = () => {
toast.add({ severity: 'info', summary: 'Info Message', detail: 'Message Detail', life: 3000 });
};
const showWarn = () => {
toast.add({ severity: 'warn', summary: 'Warn Message', detail: 'Message Detail', life: 3000 });
};
const showError = () => {
toast.add({ severity: 'error', summary: 'Error Message', detail: 'Message Detail', life: 3000 });
};
</script>
<template>
<div class="flex flex-col md:flex-row gap-4">
<div class="card md:w-1/2">
<h5 class="mb-2">Toast</h5>
<div class="flex flex-wrap gap-2">
<Button @click="showSuccess()" label="Success" severity="success" />
<Button @click="showInfo()" label="Info" severity="info" />
<Button @click="showWarn()" label="Warn" severity="warning" />
<Button @click="showError()" label="Error" severity="danger" />
</div>
</div>
<div class="card md:w-1/2">
<h5 class="mb-2">Messages</h5>
<div class="flex flex-wrap gap-2 mb-4">
<Button label="Success" @click="addMessage('success')" severity="success" />
<Button label="Info" @click="addMessage('info')" severity="info" />
<Button label="Warn" @click="addMessage('warn')" severity="warning" />
<Button label="Error" @click="addMessage('error')" severity="danger" />
</div>
<transition-group name="p-message" tag="div">
<Message v-for="msg of message" :severity="msg.severity" :key="msg.content">{{ msg.content }}</Message>
</transition-group>
</div>
</div>
<div class="flex flex-col md:flex-row gap-4 mt-6">
<div class="card md:w-1/2">
<h5 class="mb-2">Inline</h5>
<div class="flex flex-wrap mb-4 gap-2">
<InputText v-model="username" placeholder="Username" aria-label="username" invalid />
<Message severity="error">Username is required</Message>
</div>
<div class="flex flex-wrap gap-2">
<InputText v-model="email" placeholder="Email" aria-label="email" invalid />
<Message severity="error" icon="pi pi-times-circle" />
</div>
</div>
<div class="card md:w-1/2">
<h5 class="mb-2">Help Text</h5>
<div class="flex flex-col gap-2">
<label for="username">Username</label>
<InputText id="username" v-model="value" aria-describedby="username-help" />
<small id="username-help">Enter your username to reset your password.</small>
</div>
</div>
</div>
</template>

195
src/views/uikit/MiscDoc.vue Normal file
View File

@@ -0,0 +1,195 @@
<script setup>
import { ref, onMounted, onBeforeUnmount } from 'vue';
const value = ref(0);
let interval = null;
const startProgress = () => {
interval = setInterval(() => {
let newValue = value.value + Math.floor(Math.random() * 10) + 1;
if (newValue >= 100) {
newValue = 100;
}
value.value = newValue;
}, 2000);
};
const endProgress = () => {
clearInterval(interval);
interval = null;
};
onMounted(() => {
startProgress();
});
onBeforeUnmount(() => {
endProgress();
});
</script>
<template>
<div class="card">
<h5>ProgressBar</h5>
<div class="flex flex-col md:flex-row gap-4">
<div class="md:w-1/2">
<ProgressBar :value="value"></ProgressBar>
</div>
<div class="md:w-1/2">
<ProgressBar :value="50" :showValue="false"></ProgressBar>
</div>
</div>
</div>
<div class="flex flex-col md:flex-row gap-4 mt-4">
<div class="md:w-1/2">
<div class="card">
<h4 class="mb-2">Badge</h4>
<h5 class="mb-2">Numbers</h5>
<div class="flex gap-2">
<Badge :value="2"></Badge>
<Badge :value="8" severity="success"></Badge>
<Badge :value="4" severity="info"></Badge>
<Badge :value="12" severity="warn"></Badge>
<Badge :value="3" severity="danger"></Badge>
</div>
<h5 class="my-4">Positioned Badge</h5>
<div class="flex gap-6">
<OverlayBadge value="2">
<i class="pi pi-bell" style="font-size: 2rem" />
</OverlayBadge>
<OverlayBadge value="4" severity="danger">
<i class="pi pi-calendar" style="font-size: 2rem" />
</OverlayBadge>
<OverlayBadge severity="danger">
<i class="pi pi-envelope" style="font-size: 2rem" />
</OverlayBadge>
</div>
<h5 class="my-4">Inline Button Badge</h5>
<Button label="Emails" badge="8" class="mr-2"></Button>
<Button label="Messages" icon="pi pi-users" severity="warn" badge="8" badgeClass="p-badge-danger"></Button>
<h5 class="my-4">Sizes</h5>
<div class="flex items-start gap-2">
<Badge :value="2"></Badge>
<Badge :value="4" size="large" severity="warn"></Badge>
<Badge :value="6" size="xlarge" severity="success"></Badge>
</div>
</div>
<div class="card">
<h4>Avatar</h4>
<h5 class="my-4">Avatar Group</h5>
<AvatarGroup>
<Avatar :image="'/demo/images/avatar/amyelsner.png'" size="large" shape="circle"></Avatar>
<Avatar :image="'/demo/images/avatar/asiyajavayant.png'" size="large" shape="circle"></Avatar>
<Avatar :image="'/demo/images/avatar/onyamalimba.png'" size="large" shape="circle"></Avatar>
<Avatar :image="'/demo/images/avatar/ionibowcher.png'" size="large" shape="circle"></Avatar>
<Avatar :image="'/demo/images/avatar/xuxuefeng.png'" size="large" shape="circle"></Avatar>
<Avatar label="+2" shape="circle" size="large" :style="{ 'background-color': '#9c27b0', color: '#ffffff' }"></Avatar>
</AvatarGroup>
<h5 class="my-4">Label - Circle</h5>
<Avatar label="P" class="mr-2" size="xlarge" shape="circle"></Avatar>
<Avatar label="V" class="mr-2" size="large" :style="{ 'background-color': '#2196F3', color: '#ffffff' }" shape="circle"></Avatar>
<Avatar label="U" class="mr-2" :style="{ 'background-color': '#9c27b0', color: '#ffffff' }" shape="circle"></Avatar>
<h5 class="my-4">Icon - Badge</h5>
<OverlayBadge value="4" severity="danger" class="inline-flex">
<Avatar label="U" size="xlarge" />
</OverlayBadge>
</div>
<div class="card">
<h4>ScrollTop</h4>
<ScrollPanel :style="{ width: '250px', height: '200px' }">
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Vitae et leo duis ut diam. Ultricies mi quis hendrerit dolor magna eget est lorem. Amet consectetur
adipiscing elit ut. Nam libero justo laoreet sit amet. Pharetra massa massa ultricies mi quis hendrerit dolor magna. Est ultricies integer quis auctor elit sed vulputate. Consequat ac felis donec et. Tellus orci ac auctor
augue mauris. Semper feugiat nibh sed pulvinar proin gravida hendrerit lectus a. Tincidunt arcu non sodales neque sodales. Metus aliquam eleifend mi in nulla posuere sollicitudin aliquam ultrices. Sodales ut etiam sit amet
nisl purus. Cursus sit amet dictum sit amet. Tristique senectus et netus et malesuada fames ac turpis egestas. Et tortor consequat id porta nibh venenatis cras sed. Diam maecenas ultricies mi eget mauris. Eget egestas purus
viverra accumsan in nisl nisi. Suscipit adipiscing bibendum est ultricies integer. Mattis aliquam faucibus purus in massa tempor nec.
</p>
<ScrollTop target="parent" :threshold="100" icon="pi pi-arrow-up"></ScrollTop>
</ScrollPanel>
</div>
</div>
<div class="md:w-1/2">
<div class="card">
<h4>Tag</h4>
<h5>Tags</h5>
<div class="flex gap-2">
<Tag value="Primary"></Tag>
<Tag severity="success" value="Success"></Tag>
<Tag severity="info" value="Info"></Tag>
<Tag severity="warn" value="Warn"></Tag>
<Tag severity="danger" value="Danger"></Tag>
</div>
<h5>Pills</h5>
<div class="flex gap-2">
<Tag value="Primary" :rounded="true"></Tag>
<Tag severity="success" value="Success" :rounded="true"></Tag>
<Tag severity="info" value="Info" :rounded="true"></Tag>
<Tag severity="warn" value="warn" :rounded="true"></Tag>
<Tag severity="danger" value="Danger" :rounded="true"></Tag>
</div>
<h5>Icons</h5>
<div class="flex gap-2">
<Tag icon="pi pi-user" value="Primary"></Tag>
<Tag icon="pi pi-check" severity="success" value="Success"></Tag>
<Tag icon="pi pi-info-circle" severity="info" value="Info"></Tag>
<Tag con="pi pi-exclamation-triangle" severity="warn" value="warn"></Tag>
<Tag icon="pi pi-times" severity="danger" value="Danger"></Tag>
</div>
</div>
<div class="card">
<h4>Chip</h4>
<h5>Basic</h5>
<div class="flex items-center flex-col sm:flex-row">
<Chip label="Action" class="mr-2 mb-2"></Chip>
<Chip label="Comedy" class="mr-2 mb-2"></Chip>
<Chip label="Mystery" class="mr-2 mb-2"></Chip>
<Chip label="Thriller" :removable="true" class="mb-2"></Chip>
</div>
<h5>Icon</h5>
<div class="flex items-center flex-col sm:flex-row">
<Chip label="Apple" icon="pi pi-apple" class="mr-2 mb-2"></Chip>
<Chip label="Facebook" icon="pi pi-facebook" class="mr-2 mb-2"></Chip>
<Chip label="Google" icon="pi pi-google" class="mr-2 mb-2"></Chip>
<Chip label="Microsoft" icon="pi pi-microsoft" :removable="true" class="mb-2"></Chip>
</div>
<h5>Image</h5>
<div class="flex items-center flex-col sm:flex-row">
<Chip label="Amy Elsner" :image="'/demo/images/avatar/amyelsner.png'" class="mr-2 mb-2"></Chip>
<Chip label="Asiya Javayant" :image="'/demo/images/avatar/asiyajavayant.png'" class="mr-2 mb-2"></Chip>
<Chip label="Onyama Limba" :image="'/demo/images/avatar/onyamalimba.png'" class="mr-2 mb-2"></Chip>
</div>
</div>
<div class="card">
<h4>Skeleton</h4>
<div class="rounded-border border border-surface p-6">
<div class="flex mb-4">
<Skeleton shape="circle" size="4rem" class="mr-2"></Skeleton>
<div>
<Skeleton width="10rem" class="mb-2"></Skeleton>
<Skeleton width="5rem" class="mb-2"></Skeleton>
<Skeleton height=".5rem"></Skeleton>
</div>
</div>
<Skeleton width="100%" height="150px"></Skeleton>
<div class="flex justify-between mt-4">
<Skeleton width="4rem" height="2rem"></Skeleton>
<Skeleton width="4rem" height="2rem"></Skeleton>
</div>
</div>
</div>
</div>
</div>
</template>

View File

@@ -0,0 +1,196 @@
<script setup>
import { ref, onMounted } from 'vue';
import { useToast } from 'primevue/usetoast';
import { useConfirm } from 'primevue/useconfirm';
import { ProductService } from '@/service/ProductService';
const display = ref(false);
const displayConfirmation = ref(false);
const visibleLeft = ref(false);
const visibleRight = ref(false);
const visibleTop = ref(false);
const visibleBottom = ref(false);
const visibleFull = ref(false);
const products = ref(null);
const selectedProduct = ref(null);
const op = ref(null);
const op2 = ref(null);
const popup = ref(null);
const toast = useToast();
const confirmPopup = useConfirm();
onMounted(() => {
ProductService.getProductsSmall().then((data) => (products.value = data));
});
const open = () => {
display.value = true;
};
const close = () => {
display.value = false;
};
const openConfirmation = () => {
displayConfirmation.value = true;
};
const closeConfirmation = () => {
displayConfirmation.value = false;
};
const toggle = (event) => {
op.value.toggle(event);
};
const toggleDataTable = (event) => {
op2.value.toggle(event);
};
const onProductSelect = (event) => {
op.value.hide();
toast.add({ severity: 'info', summary: 'Product Selected', detail: event.data.name, life: 3000 });
};
const confirm = (event) => {
confirmPopup.require({
target: event.target,
message: 'Are you sure you want to proceed?',
icon: 'pi pi-exclamation-triangle',
rejectProps: {
label: 'Cancel',
severity: 'secondary',
outlined: true
},
acceptProps: {
label: 'Save'
},
accept: () => {
toast.add({ severity: 'info', summary: 'Confirmed', detail: 'You have accepted', life: 3000 });
},
reject: () => {
toast.add({ severity: 'info', summary: 'Rejected', detail: 'You have rejected', life: 3000 });
}
});
};
</script>
<template>
<div class="flex flex-col md:flex-row gap-6">
<div class="md:w-1/2">
<div class="card">
<h5 class="mb-4">Dialog</h5>
<Dialog header="Dialog" v-model:visible="display" :breakpoints="{ '960px': '75vw' }" :style="{ width: '30vw' }" :modal="true">
<p class="leading-normal m-0">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat. 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>
<template #footer>
<Button label="Ok" @click="close" icon="pi pi-check" class="p-button-outlined" />
</template>
</Dialog>
<Button label="Show" icon="pi pi-external-link" style="width: auto" @click="open" />
</div>
<div class="card">
<h5 class="mb-4">Popover</h5>
<div class="flex flex-wrap gap-2">
<Button type="button" label="Image" @click="toggle" severity="success" />
<Popover ref="op">
<img src="https://primefaces.org/cdn/primevue/images/nature/nature9.jpg" alt="Image" />
</Popover>
<Button type="button" label="DataTable" @click="toggleDataTable" severity="success" />
<Popover ref="op2" id="overlay_panel" style="width: 450px">
<DataTable v-model:selection="selectedProduct" :value="products" selectionMode="single" :paginator="true" :rows="5" @row-select="onProductSelect">
<Column field="name" header="Name" sortable style="min-width: 12rem"></Column>
<Column header="Image">
<template #body="slotProps">
<img :src="`https://primefaces.org/cdn/primevue/images/product/${slotProps.data.image}`" :alt="slotProps.data.image" class="w-16 shadow-sm" />
</template>
</Column>
<Column field="price" header="Price" sortable style="min-width: 8rem">
<template #body="slotProps"> $ {{ slotProps.data.price }} </template>
</Column>
</DataTable>
</Popover>
</div>
</div>
<div class="card">
<h5 class="mb-4">Tooltip</h5>
<div class="inline-flex gap-4">
<InputText type="text" placeholder="Username" v-tooltip="'Your username'" />
<Button type="button" label="Save" icon="pi pi-check" v-tooltip="'Click to proceed'" />
</div>
</div>
</div>
<div class="md:w-1/2">
<div class="card">
<h5 class="mb-4">Drawer</h5>
<Drawer v-model:visible="visibleLeft" header="Drawer">
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat.
</p>
</Drawer>
<Drawer v-model:visible="visibleRight" header="Drawer" position="right">
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat.
</p>
</Drawer>
<Drawer v-model:visible="visibleTop" header="Drawer" position="top">
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat.
</p>
</Drawer>
<Drawer v-model:visible="visibleBottom" header="Drawer" position="bottom">
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat.
</p>
</Drawer>
<Drawer v-model:visible="visibleFull" header="Drawer" position="full">
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat.
</p>
</Drawer>
<Button icon="pi pi-arrow-right" severity="warn" @click="visibleLeft = true" style="margin-right: 0.25em" />
<Button icon="pi pi-arrow-left" severity="warn" @click="visibleRight = true" style="margin-right: 0.25em" />
<Button icon="pi pi-arrow-down" severity="warn" @click="visibleTop = true" style="margin-right: 0.25em" />
<Button icon="pi pi-arrow-up" severity="warn" @click="visibleBottom = true" style="margin-right: 0.25em" />
<Button icon="pi pi-external-link" severity="warn" @click="visibleFull = true" />
</div>
<div class="card">
<h5 class="mb-4">ConfirmPopup</h5>
<ConfirmPopup></ConfirmPopup>
<Button ref="popup" @click="confirm($event)" icon="pi pi-check" label="Confirm" class="mr-2"></Button>
</div>
<div class="card">
<h5 class="mb-4">Confirmation</h5>
<Button label="Delete" icon="pi pi-trash" severity="danger" style="width: auto" @click="openConfirmation" />
<Dialog header="Confirmation" v-model:visible="displayConfirmation" :style="{ width: '350px' }" :modal="true">
<div class="flex items-center justify-center">
<i class="pi pi-exclamation-triangle mr-4" style="font-size: 2rem" />
<span>Are you sure you want to proceed?</span>
</div>
<template #footer>
<Button label="No" icon="pi pi-times" @click="closeConfirmation" class="p-button-text" />
<Button label="Yes" icon="pi pi-check" @click="closeConfirmation" class="p-button-text" autofocus />
</template>
</Dialog>
</div>
</div>
</div>
</template>

View File

@@ -0,0 +1,217 @@
<script setup>
import { ref } from 'vue';
const items = ref([
{
label: 'Save',
icon: 'pi pi-check'
},
{
label: 'Update',
icon: 'pi pi-upload'
},
{
label: 'Delete',
icon: 'pi pi-trash'
},
{
label: 'Home Page',
icon: 'pi pi-home'
}
]);
const cardMenu = ref([
{ label: 'Save', icon: 'pi pi-fw pi-check' },
{ label: 'Update', icon: 'pi pi-fw pi-refresh' },
{ label: 'Delete', icon: 'pi pi-fw pi-trash' }
]);
const menuRef = ref(null);
const toggle = () => {
menuRef.value.toggle(event);
};
</script>
<template>
<div class="flex flex-col gap-4">
<div class="card">
<h5>Toolbar</h5>
<Toolbar>
<template #start>
<Button icon="pi pi-plus" class="mr-2" severity="secondary" text />
<Button icon="pi pi-print" class="mr-2" severity="secondary" text />
<Button icon="pi pi-upload" severity="secondary" text />
</template>
<template #center>
<IconField>
<InputIcon>
<i class="pi pi-search" />
</InputIcon>
<InputText placeholder="Search" />
</IconField>
</template>
<template #end> <SplitButton label="Save" :model="items"></SplitButton></template>
</Toolbar>
</div>
<div class="flex flex-col md:flex-row gap-4">
<div class="md:w-1/2">
<div class="card">
<h5>Accordion</h5>
<Accordion value="0">
<AccordionPanel value="0">
<AccordionHeader>Header I</AccordionHeader>
<AccordionContent>
<p class="m-0">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea
commodo consequat. 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>
</AccordionContent>
</AccordionPanel>
<AccordionPanel value="1">
<AccordionHeader>Header II</AccordionHeader>
<AccordionContent>
<p class="m-0">
Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt
explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Consectetur, adipisci velit, sed quia non
numquam eius modi.
</p>
</AccordionContent>
</AccordionPanel>
<AccordionPanel value="2">
<AccordionHeader>Header III</AccordionHeader>
<AccordionContent>
<p class="m-0">
At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique
sunt in culpa qui officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil
impedit quo minus.
</p>
</AccordionContent>
</AccordionPanel>
</Accordion>
</div>
<div class="card">
<h5>Tabs</h5>
<Tabs value="0">
<TabList>
<Tab value="0">Header I</Tab>
<Tab value="1">Header II</Tab>
<Tab value="2">Header III</Tab>
</TabList>
<TabPanels>
<TabPanel value="0">
<p class="m-0">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea
commodo consequat. 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>
</TabPanel>
<TabPanel value="1">
<p class="m-0">
Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt
explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Consectetur, adipisci velit, sed quia non
numquam eius modi.
</p>
</TabPanel>
<TabPanel value="2">
<p class="m-0">
At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique
sunt in culpa qui officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil
impedit quo minus.
</p>
</TabPanel>
</TabPanels>
</Tabs>
</div>
</div>
<div class="md:w-1/2 mt-6 md:mt-0">
<div class="card">
<h5>Panel</h5>
<Panel header="Header" :toggleable="true">
<p class="leading-normal m-0">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat. 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>
</Panel>
</div>
<div class="card">
<h5>Fieldset</h5>
<Fieldset legend="Legend" :toggleable="true">
<p class="leading-normal m-0">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat. 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>
</Fieldset>
</div>
<Card>
<template v-slot:title>
<div class="flex items-center justify-between mb-0">
<h5>Card</h5>
<Button icon="pi pi-plus" class="p-button-text" @click="toggle" />
</div>
<Menu id="config_menu" ref="menuRef" :model="cardMenu" :popup="true" />
</template>
<template v-slot:content>
<p class="leading-normal m-0">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat. 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>
</template>
</Card>
</div>
</div>
<div class="card mt-4">
<h5>Divider</h5>
<div class="flex flex-col md:flex-row">
<div class="w-full md:w-5/12 flex flex-col items-center justify-center gap-3 py-5">
<div class="flex flex-col gap-2">
<label for="username">Username</label>
<InputText id="username" type="text" />
</div>
<div class="flex flex-col gap-2">
<label for="password">Password</label>
<InputText id="password" type="password" />
</div>
<div class="flex">
<Button label="Login" icon="pi pi-user" class="w-full max-w-[17.35rem] mx-auto"></Button>
</div>
</div>
<div class="w-full md:w-2/12">
<Divider layout="vertical" class="hidden md:flex"><b>OR</b></Divider>
<Divider layout="horizontal" class="flex md:hidden" align="center"><b>OR</b></Divider>
</div>
<div class="w-full md:w-5/12 flex items-center justify-center py-5">
<Button label="Sign Up" icon="pi pi-user-plus" severity="success" class="w-full max-w-[17.35rem] mx-auto"></Button>
</div>
</div>
</div>
<div class="card">
<h5>Splitter</h5>
<Splitter style="height: 300px" class="mb-8">
<SplitterPanel :size="30" :minSize="10">
<div className="h-full flex items-center justify-center">Panel 1</div>
</SplitterPanel>
<SplitterPanel :size="70">
<Splitter layout="vertical">
<SplitterPanel :size="15">
<div className="h-full flex items-center justify-center">Panel 2</div>
</SplitterPanel>
<SplitterPanel :size="50">
<div className="h-full flex items-center justify-center">Panel 3</div>
</SplitterPanel>
</Splitter>
</SplitterPanel>
</Splitter>
</div>
</div>
</template>

View File

@@ -0,0 +1,394 @@
<script setup>
import { ref, onBeforeMount, reactive } from 'vue';
import { FilterMatchMode, FilterOperator } from '@primevue/core/api';
import { CustomerService } from '@/service/CustomerService';
import { ProductService } from '@/service/ProductService';
const customers1 = ref(null);
const customers2 = ref(null);
const customers3 = ref(null);
const filters1 = ref(null);
const loading1 = ref(null);
const balanceFrozen = ref(false);
const products = ref(null);
const expandedRows = ref([]);
const statuses = reactive(['unqualified', 'qualified', 'new', 'negotiation', 'renewal', 'proposal']);
const representatives = reactive([
{ name: 'Amy Elsner', image: 'amyelsner.png' },
{ name: 'Anna Fali', image: 'annafali.png' },
{ name: 'Asiya Javayant', image: 'asiyajavayant.png' },
{ name: 'Bernardo Dominic', image: 'bernardodominic.png' },
{ name: 'Elwin Sharvill', image: 'elwinsharvill.png' },
{ name: 'Ioni Bowcher', image: 'ionibowcher.png' },
{ name: 'Ivan Magalhaes', image: 'ivanmagalhaes.png' },
{ name: 'Onyama Limba', image: 'onyamalimba.png' },
{ name: 'Stephen Shaw', image: 'stephenshaw.png' },
{ name: 'XuXue Feng', image: 'xuxuefeng.png' }
]);
const getOrderSeverity = (order) => {
switch (order.status) {
case 'DELIVERED':
return 'success';
case 'CANCELLED':
return 'danger';
case 'PENDING':
return 'warn';
case 'RETURNED':
return 'info';
default:
return null;
}
};
const getSeverity = (status) => {
switch (status) {
case 'unqualified':
return 'danger';
case 'qualified':
return 'success';
case 'new':
return 'info';
case 'negotiation':
return 'warn';
case 'renewal':
return null;
}
};
const getStockSeverity = (product) => {
switch (product.inventoryStatus) {
case 'INSTOCK':
return 'success';
case 'LOWSTOCK':
return 'warn';
case 'OUTOFSTOCK':
return 'danger';
default:
return null;
}
};
onBeforeMount(() => {
ProductService.getProductsWithOrdersSmall().then((data) => (products.value = data));
CustomerService.getCustomersLarge().then((data) => {
customers1.value = data;
loading1.value = false;
customers1.value.forEach((customer) => (customer.date = new Date(customer.date)));
});
CustomerService.getCustomersLarge().then((data) => (customers2.value = data));
CustomerService.getCustomersMedium().then((data) => (customers3.value = data));
initFilters1();
});
const initFilters1 = () => {
filters1.value = {
global: { value: null, matchMode: FilterMatchMode.CONTAINS },
name: { operator: FilterOperator.AND, constraints: [{ value: null, matchMode: FilterMatchMode.STARTS_WITH }] },
'country.name': { operator: FilterOperator.AND, constraints: [{ value: null, matchMode: FilterMatchMode.STARTS_WITH }] },
representative: { value: null, matchMode: FilterMatchMode.IN },
date: { operator: FilterOperator.AND, constraints: [{ value: null, matchMode: FilterMatchMode.DATE_IS }] },
balance: { operator: FilterOperator.AND, constraints: [{ value: null, matchMode: FilterMatchMode.EQUALS }] },
status: { operator: FilterOperator.OR, constraints: [{ value: null, matchMode: FilterMatchMode.EQUALS }] },
activity: { value: [0, 100], matchMode: FilterMatchMode.BETWEEN },
verified: { value: null, matchMode: FilterMatchMode.EQUALS }
};
};
const expandAll = () => {
expandedRows.value = products.value.reduce((acc, p) => (acc[p.id] = true) && acc, {});
};
const collapseAll = () => {
expandedRows.value = null;
};
const formatCurrency = (value) => {
return value.toLocaleString('en-US', { style: 'currency', currency: 'USD' });
};
const formatDate = (value) => {
return value.toLocaleDateString('en-US', {
day: '2-digit',
month: '2-digit',
year: 'numeric'
});
};
const calculateCustomerTotal = (name) => {
let total = 0;
if (customers3.value) {
for (let customer of customers3.value) {
if (customer.representative.name === name) {
total++;
}
}
}
return total;
};
</script>
<template>
<div class="card">
<h5>Filter Menu</h5>
<DataTable
:value="customers1"
: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
>
<template #header>
<div class="flex justify-between">
<Button type="button" icon="pi pi-filter-slash" label="Clear" outlined @click="clearFilter()" />
<IconField>
<InputIcon>
<i class="pi pi-search" />
</InputIcon>
<InputText v-model="filters1['global'].value" placeholder="Keyword Search" />
</IconField>
</div>
</template>
<template #empty> No customers found. </template>
<template #loading> Loading customers data. Please wait. </template>
<Column field="name" header="Name" style="min-width: 12rem">
<template #body="{ data }">
{{ data.name }}
</template>
<template #filter="{ filterModel }">
<InputText v-model="filterModel.value" type="text" placeholder="Search by name" />
</template>
</Column>
<Column header="Country" filterField="country.name" style="min-width: 12rem">
<template #body="{ data }">
<div class="flex items-center gap-2">
<img alt="flag" src="https://primefaces.org/cdn/primevue/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 v-model="filterModel.value" type="text" placeholder="Search by country" />
</template>
<template #filterclear="{ filterCallback }">
<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>
</template>
<template #filterfooter>
<div class="px-4 pt-0 pb-4 text-center">Customized Buttons</div>
</template>
</Column>
<Column header="Agent" filterField="representative" :showFilterMatchModes="false" :filterMenuStyle="{ width: '14rem' }" style="min-width: 14rem">
<template #body="{ data }">
<div class="flex items-center gap-2">
<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 }">
<MultiSelect v-model="filterModel.value" :options="representatives" optionLabel="name" placeholder="Any">
<template #option="slotProps">
<div class="flex items-center gap-2">
<img :alt="slotProps.option.name" :src="`https://primefaces.org/cdn/primevue/images/avatar/${slotProps.option.image}`" style="width: 32px" />
<span>{{ slotProps.option.name }}</span>
</div>
</template>
</MultiSelect>
</template>
</Column>
<Column header="Date" filterField="date" dataType="date" style="min-width: 10rem">
<template #body="{ data }">
{{ formatDate(data.date) }}
</template>
<template #filter="{ filterModel }">
<DatePicker v-model="filterModel.value" dateFormat="mm/dd/yy" placeholder="mm/dd/yyyy" />
</template>
</Column>
<Column header="Balance" filterField="balance" dataType="numeric" style="min-width: 10rem">
<template #body="{ data }">
{{ formatCurrency(data.balance) }}
</template>
<template #filter="{ filterModel }">
<InputNumber v-model="filterModel.value" mode="currency" currency="USD" locale="en-US" />
</template>
</Column>
<Column header="Status" field="status" :filterMenuStyle="{ width: '14rem' }" style="min-width: 12rem">
<template #body="{ data }">
<Tag :value="data.status" :severity="getSeverity(data.status)" />
</template>
<template #filter="{ filterModel }">
<Select v-model="filterModel.value" :options="statuses" placeholder="Select One" showClear>
<template #option="slotProps">
<Tag :value="slotProps.option" :severity="getSeverity(slotProps.option)" />
</template>
</Select>
</template>
</Column>
<Column field="activity" header="Activity" :showFilterMatchModes="false" style="min-width: 12rem">
<template #body="{ data }">
<ProgressBar :value="data.activity" :showValue="false" style="height: 6px"></ProgressBar>
</template>
<template #filter="{ filterModel }">
<Slider v-model="filterModel.value" range class="m-4"></Slider>
<div class="flex items-center justify-between px-2">
<span>{{ filterModel.value ? filterModel.value[0] : 0 }}</span>
<span>{{ filterModel.value ? filterModel.value[1] : 100 }}</span>
</div>
</template>
</Column>
<Column field="verified" header="Verified" dataType="boolean" bodyClass="text-center" style="min-width: 8rem">
<template #body="{ data }">
<i class="pi" :class="{ 'pi-check-circle text-green-500 ': data.verified, 'pi-times-circle text-red-500': !data.verified }"></i>
</template>
<template #filter="{ filterModel }">
<label for="verified-filter" class="font-bold"> Verified </label>
<Checkbox v-model="filterModel.value" :indeterminate="filterModel.value === null" binary inputId="verified-filter" />
</template>
</Column>
</DataTable>
</div>
<div class="card">
<h5>Frozen Columns</h5>
<ToggleButton v-model="balanceFrozen" onIcon="pi pi-lock" offIcon="pi pi-lock-open" onLabel="Balance" offLabel="Balance" />
<DataTable :value="customers2" scrollable scrollHeight="400px" class="mt-6">
<Column field="name" header="Name" style="min-width: 200px" frozen class="font-bold"></Column>
<Column field="id" header="Id" style="min-width: 100px"></Column>
<Column field="name" header="Name" style="min-width: 200px"></Column>
<Column field="country.name" header="Country" style="min-width: 200px"></Column>
<Column field="date" header="Date" style="min-width: 200px"></Column>
<Column field="company" header="Company" style="min-width: 200px"></Column>
<Column field="status" header="Status" style="min-width: 200px"></Column>
<Column field="activity" header="Activity" style="min-width: 200px"></Column>
<Column field="representative.name" header="Representative" style="min-width: 200px"></Column>
<Column field="balance" header="Balance" style="min-width: 200px" alignFrozen="right" :frozen="balanceFrozen">
<template #body="{ data }">
<span class="font-bold">{{ formatCurrency(data.balance) }}</span>
</template>
</Column>
</DataTable>
</div>
<div class="card">
<h5>Row Expand</h5>
<DataTable v-model:expandedRows="expandedRows" :value="products" dataKey="id" tableStyle="min-width: 60rem">
<template #header>
<div class="flex flex-wrap justify-end gap-2">
<Button text icon="pi pi-plus" label="Expand All" @click="expandAll" />
<Button text icon="pi pi-minus" label="Collapse All" @click="collapseAll" />
</div>
</template>
<Column expander style="width: 5rem" />
<Column field="name" header="Name"></Column>
<Column header="Image">
<template #body="slotProps">
<img :src="`https://primefaces.org/cdn/primevue/images/product/${slotProps.data.image}`" :alt="slotProps.data.image" class="shadow-lg" width="64" />
</template>
</Column>
<Column field="price" header="Price">
<template #body="slotProps">
{{ formatCurrency(slotProps.data.price) }}
</template>
</Column>
<Column field="category" header="Category"></Column>
<Column field="rating" header="Reviews">
<template #body="slotProps">
<Rating :modelValue="slotProps.data.rating" readonly />
</template>
</Column>
<Column header="Status">
<template #body="slotProps">
<Tag :value="slotProps.data.inventoryStatus" :severity="getStockSeverity(slotProps.data)" />
</template>
</Column>
<template #expansion="slotProps">
<div class="p-4">
<h5>Orders for {{ slotProps.data.name }}</h5>
<DataTable :value="slotProps.data.orders">
<Column field="id" header="Id" sortable></Column>
<Column field="customer" header="Customer" sortable></Column>
<Column field="date" header="Date" sortable></Column>
<Column field="amount" header="Amount" sortable>
<template #body="slotProps">
{{ formatCurrency(slotProps.data.amount) }}
</template>
</Column>
<Column field="status" header="Status" sortable>
<template #body="slotProps">
<Tag :value="slotProps.data.status.toLowerCase()" :severity="getOrderSeverity(slotProps.data)" />
</template>
</Column>
<Column headerStyle="width:4rem">
<template #body>
<Button icon="pi pi-search" />
</template>
</Column>
</DataTable>
</div>
</template>
</DataTable>
</div>
<div class="card">
<h5>Subheader Grouping</h5>
<DataTable :value="customers3" rowGroupMode="subheader" groupRowsBy="representative.name" sortMode="single" sortField="representative.name" :sortOrder="1" scrollable scrollHeight="400px" tableStyle="min-width: 50rem">
<template #groupheader="slotProps">
<div class="flex items-center gap-2">
<img :alt="slotProps.data.representative.name" :src="`https://primefaces.org/cdn/primevue/images/avatar/${slotProps.data.representative.image}`" width="32" style="vertical-align: middle" />
<span>{{ slotProps.data.representative.name }}</span>
</div>
</template>
<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="slotProps">
<div class="flex items-center gap-2">
<img alt="flag" src="https://primefaces.org/cdn/primevue/images/flag/flag_placeholder.png" :class="`flag flag-${slotProps.data.country.code}`" style="width: 24px" />
<span>{{ slotProps.data.country.name }}</span>
</div>
</template>
</Column>
<Column field="company" header="Company" style="min-width: 200px"></Column>
<Column field="status" header="Status" style="min-width: 200px">
<template #body="slotProps">
<Tag :value="slotProps.data.status" :severity="getSeverity(slotProps.data.status)" />
</template>
</Column>
<Column field="date" header="Date" style="min-width: 200px"></Column>
<template #groupfooter="slotProps">
<div class="flex justify-end font-bold w-full">Total Customers: {{ calculateCustomerTotal(slotProps.data.representative.name) }}</div>
</template>
</DataTable>
</div>
</template>
<style scoped lang="scss">
:deep(.p-datatable-frozen-tbody) {
font-weight: bold;
}
:deep(.p-datatable-scrollable .p-frozen-column) {
font-weight: bold;
}
</style>

View File

@@ -0,0 +1,31 @@
<script setup>
import { onMounted, ref } from 'vue';
import { NodeService } from '@/service/NodeService';
const treeValue = ref(null);
const selectedTreeValue = ref(null);
const treeTableValue = ref(null);
const selectedTreeTableValue = ref(null);
onMounted(() => {
NodeService.getTreeNodes().then((data) => (treeValue.value = data));
NodeService.getTreeTableNodes().then((data) => (treeTableValue.value = data));
});
</script>
<template>
<div class="card">
<h5 class="mb-4">Tree</h5>
<Tree :value="treeValue" selectionMode="checkbox" v-model:selectionKeys="selectedTreeValue"></Tree>
</div>
<div class="card">
<h5 class="mb-4">TreeTable</h5>
<TreeTable :value="treeTableValue" selectionMode="checkbox" v-model:selectionKeys="selectedTreeTableValue">
<template #header> FileSystem </template>
<Column field="name" header="Name" :expander="true"></Column>
<Column field="size" header="Size"></Column>
<Column field="type" header="Type"></Column>
</TreeTable>
</div>
</template>

View File

@@ -0,0 +1,6 @@
<template>
<div class="flex items-center py-8 px-4">
<i class="pi pi-fw pi-check mr-2 text-2xl" />
<p class="m-0 text-lg">Confirmation Component Content via Child Route</p>
</div>
</template>

View File

@@ -0,0 +1,6 @@
<template>
<div class="flex items-center py-8 px-4">
<i class="pi pi-fw pi-money-bill mr-2 text-2xl" />
<p class="m-0 text-lg">Payment Component Content via Child Route</p>
</div>
</template>

View File

@@ -0,0 +1,6 @@
<template>
<div class="flex items-center py-8 px-4">
<i class="pi pi-fw pi-user mr-2 text-2xl" />
<p class="m-0 text-lg">Personal Component Content via Child Route</p>
</div>
</template>

View File

@@ -0,0 +1,6 @@
<template>
<div class="flex items-center py-8 px-4">
<i class="pi pi-fw pi-ticket mr-2 text-2xl" />
<p class="m-0 text-lg">Seat Component Content via Child Route</p>
</div>
</template>

View File

@@ -0,0 +1,806 @@
<script setup>
import { ref } from 'vue';
const block1 = ref(` <div class="grid grid-cols-12 gap-4 grid-nogutter bg-surface-0 dark:bg-surface-950 text-surface-800 dark:text-surface-50">
<div class="col-span-12 md:col-span-6 p-12 text-center md:text-left flex items-center ">
<section>
<span class="block text-6xl font-bold mb-1">Create the screens your</span>
<div class="text-6xl text-primary font-bold mb-4">your visitors deserve to see</div>
<p class="mt-0 mb-6 text-surface-700 dark:text-surface-100 leading-normal">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>
<Button label="Learn More" type="button" class="mr-4 p-button-raised"></Button>
<Button label="Live Demo" type="button" class="p-button-outlined"></Button>
</section>
</div>
<div class="col-span-12 md:col-span-6 overflow-hidden">
<img src="/demo/images/blocks/hero/hero-1.png" alt="Image" class="md:ml-auto block md:h-full" style="clip-path: polygon(8% 0, 100% 0%, 100% 100%, 0 100%)">
</div>
</div>`);
const block2 = ref(` <div class="bg-surface-0 dark:bg-surface-950 px-6 py-20 md:px-12 lg:px-20 text-center">
<div class="mb-4 font-bold text-2xl">
<span class="text-surface-900 dark:text-surface-0">One Product, </span>
<span class="text-blue-600">Many Solutions</span>
</div>
<div class="text-surface-700 dark:text-surface-100 text-sm mb-12">Ac turpis egestas maecenas pharetra convallis posuere morbi leo urna.</div>
<div class="grid grid-cols-12 gap-4">
<div class="col-span-12 md:col-span-4 mb-6 px-8">
<span class="p-4 shadow mb-4 inline-block bg-surface-0 dark:bg-surface-900" style="border-radius: 10px">
<i class="pi pi-desktop text-4xl text-blue-500"></i>
</span>
<div class="text-surface-900 dark:text-surface-0 mb-4 font-medium">Built for Developers</div>
<span class="text-surface-700 dark:text-surface-100 text-sm leading-normal">Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.</span>
</div>
<div class="col-span-12 md:col-span-4 mb-6 px-8">
<span class="p-4 shadow mb-4 inline-block bg-surface-0 dark:bg-surface-900" style="border-radius: 10px">
<i class="pi pi-lock text-4xl text-blue-500"></i>
</span>
<div class="text-surface-900 dark:text-surface-0 mb-4 font-medium">End-to-End Encryption</div>
<span class="text-surface-700 dark:text-surface-100 text-sm leading-normal">Risus nec feugiat in fermentum posuere urna nec. Posuere sollicitudin aliquam ultrices sagittis.</span>
</div>
<div class="col-span-12 md:col-span-4 mb-6 px-8">
<span class="p-4 shadow mb-4 inline-block bg-surface-0 dark:bg-surface-900" style="border-radius: 10px">
<i class="pi pi-check-circle text-4xl text-blue-500"></i>
</span>
<div class="text-surface-900 dark:text-surface-0 mb-4 font-medium">Easy to Use</div>
<span class="text-surface-700 dark:text-surface-100 text-sm leading-normal">Ornare suspendisse sed nisi lacus sed viverra tellus. Neque volutpat ac tincidunt vitae semper.</span>
</div>
<div class="col-span-12 md:col-span-4 mb-6 px-8">
<span class="p-4 shadow mb-4 inline-block bg-surface-0 dark:bg-surface-900" style="border-radius: 10px">
<i class="pi pi-globe text-4xl text-blue-500"></i>
</span>
<div class="text-surface-900 dark:text-surface-0 mb-4 font-medium">Fast & Global Support</div>
<span class="text-surface-700 dark:text-surface-100 text-sm leading-normal">Fermentum et sollicitudin ac orci phasellus egestas tellus rutrum tellus.</span>
</div>
<div class="col-span-12 md:col-span-4 mb-6 px-8">
<span class="p-4 shadow mb-4 inline-block bg-surface-0 dark:bg-surface-900" style="border-radius: 10px">
<i class="pi pi-github text-4xl text-blue-500"></i>
</span>
<div class="text-surface-900 dark:text-surface-0 mb-4 font-medium">Open Source</div>
<span class="text-surface-700 dark:text-surface-100 text-sm leading-normal">Nec tincidunt praesent semper feugiat. Sed adipiscing diam donec adipiscing tristique risus nec feugiat. </span>
</div>
<div class="col-span-12 md:col-span-4 md:mb-6 mb-0 px-4">
<span class="p-4 shadow mb-4 inline-block bg-surface-0 dark:bg-surface-900" style="border-radius: 10px">
<i class="pi pi-shield text-4xl text-blue-500"></i>
</span>
<div class="text-surface-900 dark:text-surface-0 mb-4 font-medium">Trusted Securitty</div>
<span class="text-surface-700 dark:text-surface-100 text-sm leading-normal">Mattis rhoncus urna neque viverra justo nec ultrices. Id cursus metus aliquam eleifend.</span>
</div>
</div>
</div>`);
const block3 = ref(` <div class="bg-surface-50 dark:bg-surface-950 px-6 py-20 md:px-12 lg:px-20">
<div class="text-surface-900 dark:text-surface-0 font-bold text-6xl mb-6 text-center">Pricing Plans</div>
<div class="text-surface-700 dark:text-surface-100 text-xl mb-12 text-center leading-normal">Lorem ipsum dolor sit, amet consectetur adipisicing elit. Velit numquam eligendi quos.</div>
<div class="grid grid-cols-12 gap-4">
<div class="col-span-12 lg:col-span-4">
<div class="p-4 h-full">
<div class="shadow p-4 h-full flex flex-col bg-surface-0 dark:bg-surface-900" style="border-radius: 6px">
<div class="text-surface-900 dark:text-surface-0 font-medium text-xl mb-2">Basic</div>
<div class="text-surface-600 dark:text-surface-200">Plan description</div>
<hr class="my-4 mx-0 border-t border-0 border-surface" />
<div class="flex items-center">
<span class="font-bold text-2xl text-surface-900 dark:text-surface-0">$9</span>
<span class="ml-2 font-medium text-surface-600 dark:text-surface-200">per month</span>
</div>
<hr class="my-4 mx-0 border-t border-0 border-surface" />
<ul class="list-none p-0 m-0 grow">
<li class="flex items-center mb-4">
<i class="pi pi-check-circle text-green-500 mr-2"></i>
<span>Arcu vitae elementum</span>
</li>
<li class="flex items-center mb-4">
<i class="pi pi-check-circle text-green-500 mr-2"></i>
<span>Dui faucibus in ornare</span>
</li>
<li class="flex items-center mb-4">
<i class="pi pi-check-circle text-green-500 mr-2"></i>
<span>Morbi tincidunt augue</span>
</li>
</ul>
<hr class="mb-4 mx-0 border-t border-0 border-surface mt-auto" />
<Button label="Buy Now" class="p-4 w-full mt-auto"></Button>
</div>
</div>
</div>
<div class="col-span-12 lg:col-span-4">
<div class="p-4 h-full">
<div class="shadow p-4 h-full flex flex-col bg-surface-0 dark:bg-surface-900" style="border-radius: 6px">
<div class="text-surface-900 dark:text-surface-0 font-medium text-xl mb-2">Premium</div>
<div class="text-surface-600 dark:text-surface-200">Plan description</div>
<hr class="my-4 mx-0 border-t border-0 border-surface" />
<div class="flex items-center">
<span class="font-bold text-2xl text-surface-900 dark:text-surface-0">$29</span>
<span class="ml-2 font-medium text-surface-600 dark:text-surface-200">per month</span>
</div>
<hr class="my-4 mx-0 border-t border-0 border-surface" />
<ul class="list-none p-0 m-0 grow">
<li class="flex items-center mb-4">
<i class="pi pi-check-circle text-green-500 mr-2"></i>
<span>Arcu vitae elementum</span>
</li>
<li class="flex items-center mb-4">
<i class="pi pi-check-circle text-green-500 mr-2"></i>
<span>Dui faucibus in ornare</span>
</li>
<li class="flex items-center mb-4">
<i class="pi pi-check-circle text-green-500 mr-2"></i>
<span>Morbi tincidunt augue</span>
</li>
<li class="flex items-center mb-4">
<i class="pi pi-check-circle text-green-500 mr-2"></i>
<span>Duis ultricies lacus sed</span>
</li>
</ul>
<hr class="mb-4 mx-0 border-t border-0 border-surface" />
<Button label="Buy Now" class="p-4 w-full"></Button>
</div>
</div>
</div>
<div class="col-span-12 lg:col-span-4">
<div class="p-4 h-full">
<div class="shadow p-4 flex flex-col bg-surface-0 dark:bg-surface-900" style="border-radius: 6px">
<div class="text-surface-900 dark:text-surface-0 font-medium text-xl mb-2">Enterprise</div>
<div class="text-surface-600 dark:text-surface-200">Plan description</div>
<hr class="my-4 mx-0 border-t border-0 border-surface" />
<div class="flex items-center">
<span class="font-bold text-2xl text-surface-900 dark:text-surface-0">$49</span>
<span class="ml-2 font-medium text-surface-600 dark:text-surface-200">per month</span>
</div>
<hr class="my-4 mx-0 border-t border-0 border-surface" />
<ul class="list-none p-0 m-0 grow">
<li class="flex items-center mb-4">
<i class="pi pi-check-circle text-green-500 mr-2"></i>
<span>Arcu vitae elementum</span>
</li>
<li class="flex items-center mb-4">
<i class="pi pi-check-circle text-green-500 mr-2"></i>
<span>Dui faucibus in ornare</span>
</li>
<li class="flex items-center mb-4">
<i class="pi pi-check-circle text-green-500 mr-2"></i>
<span>Morbi tincidunt augue</span>
</li>
<li class="flex items-center mb-4">
<i class="pi pi-check-circle text-green-500 mr-2"></i>
<span>Duis ultricies lacus sed</span>
</li>
<li class="flex items-center mb-4">
<i class="pi pi-check-circle text-green-500 mr-2"></i>
<span>Imperdiet proin</span>
</li>
<li class="flex items-center mb-4">
<i class="pi pi-check-circle text-green-500 mr-2"></i>
<span>Nisi scelerisque</span>
</li>
</ul>
<hr class="mb-4 mx-0 border-t border-0 border-surface" />
<Button label="Buy Now" class="p-4 w-full p-button-outlined"></Button>
</div>
</div>
</div>
</div>
</div>`);
const block4 = ref(` <div class="bg-surface-0 dark:bg-surface-950 px-6 py-20 md:px-12 lg:px-20">
<div class="text-surface-700 dark:text-surface-100 text-center">
<div class="text-blue-600 font-bold mb-4"><i class="pi pi-discord"></i>&nbsp;POWERED BY DISCORD</div>
<div class="text-surface-900 dark:text-surface-0 font-bold text-5xl mb-4">Join Our Design Community</div>
<div class="text-surface-700 dark:text-surface-100 text-2xl mb-8">Lorem ipsum dolor sit, amet consectetur adipisicing elit. Velit numquam eligendi quos.</div>
<Button label="Join Now" icon="pi pi-discord" class="font-bold px-8 py-4 p-button-raised p-button-rounded whitespace-nowrap"></Button>
</div>
</div>`);
const block5 = ref(` <div class="bg-slate-900 text-gray-100 p-4 flex justify-between lg:justify-center items-center flex-wrap">
<div class="font-bold mr-20">🔥 Hot Deals!</div>
<div class="items-center hidden lg:flex">
<span class="leading-normal">Libero voluptatum atque exercitationem praesentium provident odit.</span>
</div>
<a class="flex items-center ml-2 mr-20">
<a class="text-white" href="#"><span class="underline font-bold">Learn More</span></a>
</a>
<a v-ripple class="flex items-center no-underline justify-center rounded-full text-gray-50 hover:bg-slate-700 cursor-pointer transition-colors duration-150 p-ripple" style="width:2rem; height: 2rem">
<i class="pi pi-times"></i>
</a>
</div>`);
const block6 = ref(` <div class="bg-surface-0 dark:bg-surface-950 px-6 py-8 md:px-12 lg:px-20">
<ul class="list-none p-0 m-0 flex items-center font-medium mb-4">
<li>
<a class="text-surface-500 dark:text-surface-300 no-underline leading-normal cursor-pointer">Application</a>
</li>
<li class="px-2">
<i class="pi pi-angle-right text-surface-500 dark:text-surface-300 leading-normal"></i>
</li>
<li>
<span class="text-surface-900 dark:text-surface-0 leading-normal">Analytics</span>
</li>
</ul>
<div class="flex items-start flex-col lg:justify-between lg:flex-row">
<div>
<div class="font-medium text-3xl text-surface-900 dark:text-surface-0">Customers</div>
<div class="flex items-center text-surface-700 dark:text-surface-100 flex-wrap">
<div class="mr-8 flex items-center mt-4">
<i class="pi pi-users mr-2"></i>
<span>332 Active Users</span>
</div>
<div class="mr-8 flex items-center mt-4">
<i class="pi pi-globe mr-2"></i>
<span>9402 Sessions</span>
</div>
<div class="flex items-center mt-4">
<i class="pi pi-clock mr-2"></i>
<span>2.32m Avg. Duration</span>
</div>
</div>
</div>
<div class="mt-4 lg:mt-0">
<Button label="Add" class="p-button-outlined mr-2" icon="pi pi-user-plus"></Button>
<Button label="Save" icon="pi pi-check"></Button>
</div>
</div>
</div>`);
const block7 = ref(` <div class="bg-surface-50 dark:bg-surface-950 px-6 py-8 md:px-12 lg:px-20">
<div class="grid grid-cols-12 gap-4">
<div class="col-span-12 md:col-span-6 lg:col-span-3">
<div class="bg-surface-0 dark:bg-surface-900 shadow p-4 rounded-border">
<div class="flex justify-between mb-4">
<div>
<span class="block text-surface-500 dark:text-surface-300 font-medium mb-4">Orders</span>
<div class="text-surface-900 dark:text-surface-0 font-medium text-xl">152</div>
</div>
<div class="flex items-center justify-center bg-blue-100 rounded-border" style="width:2.5rem;height:2.5rem">
<i class="pi pi-shopping-cart text-blue-500 text-xl"></i>
</div>
</div>
<span class="text-green-500 font-medium">24 new </span>
<span class="text-surface-500 dark:text-surface-300">since last visit</span>
</div>
</div>
<div class="col-span-12 md:col-span-6 lg:col-span-3">
<div class="bg-surface-0 dark:bg-surface-900 shadow p-4 rounded-border">
<div class="flex justify-between mb-4">
<div>
<span class="block text-surface-500 dark:text-surface-300 font-medium mb-4">Revenue</span>
<div class="text-surface-900 dark:text-surface-0 font-medium text-xl">$2.100</div>
</div>
<div class="flex items-center justify-center bg-orange-100 rounded-border" style="width:2.5rem;height:2.5rem">
<i class="pi pi-map-marker text-orange-500 text-xl"></i>
</div>
</div>
<span class="text-green-500 font-medium">%52+ </span>
<span class="text-surface-500 dark:text-surface-300">since last week</span>
</div>
</div>
<div class="col-span-12 md:col-span-6 lg:col-span-3">
<div class="bg-surface-0 dark:bg-surface-900 shadow p-4 rounded-border">
<div class="flex justify-between mb-4">
<div>
<span class="block text-surface-500 dark:text-surface-300 font-medium mb-4">Customers</span>
<div class="text-surface-900 dark:text-surface-0 font-medium text-xl">28441</div>
</div>
<div class="flex items-center justify-center bg-cyan-100 rounded-border" style="width:2.5rem;height:2.5rem">
<i class="pi pi-inbox text-cyan-500 text-xl"></i>
</div>
</div>
<span class="text-green-500 font-medium">520 </span>
<span class="text-surface-500 dark:text-surface-300">newly registered</span>
</div>
</div>
<div class="col-span-12 md:col-span-6 lg:col-span-3">
<div class="bg-surface-0 dark:bg-surface-900 shadow p-4 rounded-border">
<div class="flex justify-between mb-4">
<div>
<span class="block text-surface-500 dark:text-surface-300 font-medium mb-4">Comments</span>
<div class="text-surface-900 dark:text-surface-0 font-medium text-xl">152 Unread</div>
</div>
<div class="flex items-center justify-center bg-purple-100 rounded-border" style="width:2.5rem;height:2.5rem">
<i class="pi pi-comment text-purple-500 text-xl"></i>
</div>
</div>
<span class="text-green-500 font-medium">85 </span>
<span class="text-surface-500 dark:text-surface-300">responded</span>
</div>
</div>
</div>
</div>`);
const block8 = ref(` <div class="bg-surface-0 dark:bg-surface-900 p-6 shadow rounded-border w-full lg:w-6/12">
<div class="text-center mb-8">
<img src="/demo/images/blocks/logos/hyper.svg" alt="Image" height="50" class="mb-4">
<div class="text-surface-900 dark:text-surface-0 text-3xl font-medium mb-4">Welcome Back</div>
<span class="text-surface-600 dark:text-surface-200 font-medium leading-normal">Don't have an account?</span>
<a class="font-medium no-underline ml-2 text-blue-500 cursor-pointer">Create today!</a>
</div>
<div>
<label for="email1" class="block text-surface-900 dark:text-surface-0 font-medium mb-2">Email</label>
<InputText id="email1" type="text" class="w-full mb-4" />
<label for="password1" class="block text-surface-900 dark:text-surface-0 font-medium mb-2">Password</label>
<InputText id="password1" type="password" class="w-full mb-4" />
<div class="flex items-center justify-between mb-12">
<div class="flex items-center">
<Checkbox id="rememberme1" :binary="true" v-model="checked" class="mr-2"></Checkbox>
<label for="rememberme1">Remember me</label>
</div>
<a class="font-medium no-underline ml-2 text-blue-500 text-right cursor-pointer">Forgot password?</a>
</div>
<Button label="Sign In" icon="pi pi-user" class="w-full"></Button>
</div>
</div>`);
const block9 = ref(` <div class="bg-surface-0 dark:bg-surface-950">
<div class="font-medium text-3xl text-surface-900 dark:text-surface-0 mb-4">Movie Information</div>
<div class="text-surface-500 dark:text-surface-300 mb-8">Morbi tristique blandit turpis. In viverra ligula id nulla hendrerit rutrum.</div>
<ul class="list-none p-0 m-0">
<li class="flex items-center py-4 px-2 border-t border-surface flex-wrap">
<div class="text-surface-500 dark:text-surface-300 w-6/12 md:w-2/12 font-medium">Title</div>
<div class="text-surface-900 dark:text-surface-0 w-full md:w-8/12 md:order-none order-1">Heat</div>
<div class="w-6/12 md:w-2/12 flex justify-end">
<Button label="Edit" icon="pi pi-pencil" class="p-button-text"></Button>
</div>
</li>
<li class="flex items-center py-4 px-2 border-t border-surface flex-wrap">
<div class="text-surface-500 dark:text-surface-300 w-6/12 md:w-2/12 font-medium">Genre</div>
<div class="text-surface-900 dark:text-surface-0 w-full md:w-8/12 md:order-none order-1">
<Chip label="Crime" class="mr-2"></Chip>
<Chip label="Drama" class="mr-2"></Chip>
<Chip label="Thriller"></Chip>
</div>
<div class="w-6/12 md:w-2/12 flex justify-end">
<Button label="Edit" icon="pi pi-pencil" class="p-button-text"></Button>
</div>
</li>
<li class="flex items-center py-4 px-2 border-t border-surface flex-wrap">
<div class="text-surface-500 dark:text-surface-300 w-6/12 md:w-2/12 font-medium">Director</div>
<div class="text-surface-900 dark:text-surface-0 w-full md:w-8/12 md:order-none order-1">Michael Mann</div>
<div class="w-6/12 md:w-2/12 flex justify-end">
<Button label="Edit" icon="pi pi-pencil" class="p-button-text"></Button>
</div>
</li>
<li class="flex items-center py-4 px-2 border-t border-surface flex-wrap">
<div class="text-surface-500 dark:text-surface-300 w-6/12 md:w-2/12 font-medium">Actors</div>
<div class="text-surface-900 dark:text-surface-0 w-full md:w-8/12 md:order-none order-1">Robert De Niro, Al Pacino</div>
<div class="w-6/12 md:w-2/12 flex justify-end">
<Button label="Edit" icon="pi pi-pencil" class="p-button-text"></Button>
</div>
</li>
<li class="flex items-center py-4 px-2 border-t border-b border-surface flex-wrap">
<div class="text-surface-500 dark:text-surface-300 w-6/12 md:w-2/12 font-medium">Plot</div>
<div class="text-surface-900 dark:text-surface-0 w-full md:w-8/12 md:order-none order-1 leading-normal">
A group of professional bank robbers start to feel the heat from police
when they unknowingly leave a clue at their latest heist.</div>
<div class="w-6/12 md:w-2/12 flex justify-end">
<Button label="Edit" icon="pi pi-pencil" class="p-button-text"></Button>
</div>
</li>
</ul>
</div>`);
const block10 = ref(` <div class="bg-surface-0 dark:bg-surface-900 p-6 shadow rounded-border">
<div class="text-3xl font-medium text-surface-900 dark:text-surface-0 mb-4">Card Title</div>
<div class="font-medium text-surface-500 dark:text-surface-300 mb-4">Vivamus id nisl interdum, blandit augue sit amet, eleifend mi.</div>
<div style="height: 150px" class="border-2 border-dashed border-surface"></div>
</div>`);
const checked = ref(false);
</script>
<template>
<div>
<BlockViewer header="Hero" :code="block1" free>
<div class="grid grid-cols-12 gap-4 grid-nogutter bg-surface-0 dark:bg-surface-950 text-surface-800 dark:text-surface-50">
<div class="col-span-12 md:col-span-6 p-12 text-center md:text-left flex items-center">
<section>
<span class="block text-6xl font-bold mb-1">Create the screens your</span>
<div class="text-6xl text-primary font-bold mb-4">your visitors deserve to see</div>
<p class="mt-0 mb-6 text-surface-700 dark:text-surface-100 leading-normal">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>
<Button label="Learn More" type="button" class="mr-4 p-button-raised"></Button>
<Button label="Live Demo" type="button" class="p-button-outlined"></Button>
</section>
</div>
<div class="col-span-12 md:col-span-6 overflow-hidden">
<img src="/demo/images/blocks/hero/hero-1.png" alt="Image" class="md:ml-auto block md:h-full" style="clip-path: polygon(8% 0, 100% 0%, 100% 100%, 0 100%)" />
</div>
</div>
</BlockViewer>
<BlockViewer header="Feature" :code="block2" free>
<div class="bg-surface-0 dark:bg-surface-950 px-6 py-20 md:px-12 lg:px-20 text-center">
<div class="mb-4 font-bold text-2xl">
<span class="text-surface-900 dark:text-surface-0">One Product, </span>
<span class="text-blue-600">Many Solutions</span>
</div>
<div class="text-surface-700 dark:text-surface-100 text-sm mb-12">Ac turpis egestas maecenas pharetra convallis posuere morbi leo urna.</div>
<div class="grid grid-cols-12 gap-4">
<div class="col-span-12 md:col-span-4 mb-6 px-8">
<span class="p-4 shadow mb-4 inline-block bg-surface-0 dark:bg-surface-900" style="border-radius: 10px">
<i class="pi pi-desktop text-4xl text-blue-500"></i>
</span>
<div class="text-surface-900 dark:text-surface-0 mb-4 font-medium">Built for Developers</div>
<span class="text-surface-700 dark:text-surface-100 text-sm leading-normal">Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.</span>
</div>
<div class="col-span-12 md:col-span-4 mb-6 px-8">
<span class="p-4 shadow mb-4 inline-block bg-surface-0 dark:bg-surface-900" style="border-radius: 10px">
<i class="pi pi-lock text-4xl text-blue-500"></i>
</span>
<div class="text-surface-900 dark:text-surface-0 mb-4 font-medium">End-to-End Encryption</div>
<span class="text-surface-700 dark:text-surface-100 text-sm leading-normal">Risus nec feugiat in fermentum posuere urna nec. Posuere sollicitudin aliquam ultrices sagittis.</span>
</div>
<div class="col-span-12 md:col-span-4 mb-6 px-8">
<span class="p-4 shadow mb-4 inline-block bg-surface-0 dark:bg-surface-900" style="border-radius: 10px">
<i class="pi pi-check-circle text-4xl text-blue-500"></i>
</span>
<div class="text-surface-900 dark:text-surface-0 mb-4 font-medium">Easy to Use</div>
<span class="text-surface-700 dark:text-surface-100 text-sm leading-normal">Ornare suspendisse sed nisi lacus sed viverra tellus. Neque volutpat ac tincidunt vitae semper.</span>
</div>
<div class="col-span-12 md:col-span-4 mb-6 px-8">
<span class="p-4 shadow mb-4 inline-block bg-surface-0 dark:bg-surface-900" style="border-radius: 10px">
<i class="pi pi-globe text-4xl text-blue-500"></i>
</span>
<div class="text-surface-900 dark:text-surface-0 mb-4 font-medium">Fast & Global Support</div>
<span class="text-surface-700 dark:text-surface-100 text-sm leading-normal">Fermentum et sollicitudin ac orci phasellus egestas tellus rutrum tellus.</span>
</div>
<div class="col-span-12 md:col-span-4 mb-6 px-8">
<span class="p-4 shadow mb-4 inline-block bg-surface-0 dark:bg-surface-900" style="border-radius: 10px">
<i class="pi pi-github text-4xl text-blue-500"></i>
</span>
<div class="text-surface-900 dark:text-surface-0 mb-4 font-medium">Open Source</div>
<span class="text-surface-700 dark:text-surface-100 text-sm leading-normal">Nec tincidunt praesent semper feugiat. Sed adipiscing diam donec adipiscing tristique risus nec feugiat. </span>
</div>
<div class="col-span-12 md:col-span-4 md:mb-6 mb-0 px-4">
<span class="p-4 shadow mb-4 inline-block bg-surface-0 dark:bg-surface-900" style="border-radius: 10px">
<i class="pi pi-shield text-4xl text-blue-500"></i>
</span>
<div class="text-surface-900 dark:text-surface-0 mb-4 font-medium">Trusted Securitty</div>
<span class="text-surface-700 dark:text-surface-100 text-sm leading-normal">Mattis rhoncus urna neque viverra justo nec ultrices. Id cursus metus aliquam eleifend.</span>
</div>
</div>
</div>
</BlockViewer>
<BlockViewer header="Pricing" :code="block3" free>
<div class="bg-surface-50 dark:bg-surface-950 px-6 py-20 md:px-12 lg:px-20">
<div class="text-surface-900 dark:text-surface-0 font-bold text-6xl mb-6 text-center">Pricing Plans</div>
<div class="text-surface-700 dark:text-surface-100 text-xl mb-12 text-center leading-normal">Lorem ipsum dolor sit, amet consectetur adipisicing elit. Velit numquam eligendi quos.</div>
<div class="grid grid-cols-12 gap-4">
<div class="col-span-12 lg:col-span-4">
<div class="p-4 h-full">
<div class="shadow p-4 h-full flex flex-col bg-surface-0 dark:bg-surface-900" style="border-radius: 6px">
<div class="text-surface-900 dark:text-surface-0 font-medium text-xl mb-2">Basic</div>
<div class="text-surface-600 dark:text-surface-200">Plan description</div>
<hr class="my-4 mx-0 border-t border-0 border-surface" />
<div class="flex items-center">
<span class="font-bold text-2xl text-surface-900 dark:text-surface-0">$9</span>
<span class="ml-2 font-medium text-surface-600 dark:text-surface-200">per month</span>
</div>
<hr class="my-4 mx-0 border-t border-0 border-surface" />
<ul class="list-none p-0 m-0 grow">
<li class="flex items-center mb-4">
<i class="pi pi-check-circle text-green-500 mr-2"></i>
<span>Arcu vitae elementum</span>
</li>
<li class="flex items-center mb-4">
<i class="pi pi-check-circle text-green-500 mr-2"></i>
<span>Dui faucibus in ornare</span>
</li>
<li class="flex items-center mb-4">
<i class="pi pi-check-circle text-green-500 mr-2"></i>
<span>Morbi tincidunt augue</span>
</li>
</ul>
<hr class="mb-4 mx-0 border-t border-0 border-surface mt-auto" />
<Button label="Buy Now" class="p-4 w-full mt-auto"></Button>
</div>
</div>
</div>
<div class="col-span-12 lg:col-span-4">
<div class="p-4 h-full">
<div class="shadow p-4 h-full flex flex-col bg-surface-0 dark:bg-surface-900" style="border-radius: 6px">
<div class="text-surface-900 dark:text-surface-0 font-medium text-xl mb-2">Premium</div>
<div class="text-surface-600 dark:text-surface-200">Plan description</div>
<hr class="my-4 mx-0 border-t border-0 border-surface" />
<div class="flex items-center">
<span class="font-bold text-2xl text-surface-900 dark:text-surface-0">$29</span>
<span class="ml-2 font-medium text-surface-600 dark:text-surface-200">per month</span>
</div>
<hr class="my-4 mx-0 border-t border-0 border-surface" />
<ul class="list-none p-0 m-0 grow">
<li class="flex items-center mb-4">
<i class="pi pi-check-circle text-green-500 mr-2"></i>
<span>Arcu vitae elementum</span>
</li>
<li class="flex items-center mb-4">
<i class="pi pi-check-circle text-green-500 mr-2"></i>
<span>Dui faucibus in ornare</span>
</li>
<li class="flex items-center mb-4">
<i class="pi pi-check-circle text-green-500 mr-2"></i>
<span>Morbi tincidunt augue</span>
</li>
<li class="flex items-center mb-4">
<i class="pi pi-check-circle text-green-500 mr-2"></i>
<span>Duis ultricies lacus sed</span>
</li>
</ul>
<hr class="mb-4 mx-0 border-t border-0 border-surface" />
<Button label="Buy Now" class="p-4 w-full"></Button>
</div>
</div>
</div>
<div class="col-span-12 lg:col-span-4">
<div class="p-4 h-full">
<div class="shadow p-4 flex flex-col bg-surface-0 dark:bg-surface-900" style="border-radius: 6px">
<div class="text-surface-900 dark:text-surface-0 font-medium text-xl mb-2">Enterprise</div>
<div class="text-surface-600 dark:text-surface-200">Plan description</div>
<hr class="my-4 mx-0 border-t border-0 border-surface" />
<div class="flex items-center">
<span class="font-bold text-2xl text-surface-900 dark:text-surface-0">$49</span>
<span class="ml-2 font-medium text-surface-600 dark:text-surface-200">per month</span>
</div>
<hr class="my-4 mx-0 border-t border-0 border-surface" />
<ul class="list-none p-0 m-0 grow">
<li class="flex items-center mb-4">
<i class="pi pi-check-circle text-green-500 mr-2"></i>
<span>Arcu vitae elementum</span>
</li>
<li class="flex items-center mb-4">
<i class="pi pi-check-circle text-green-500 mr-2"></i>
<span>Dui faucibus in ornare</span>
</li>
<li class="flex items-center mb-4">
<i class="pi pi-check-circle text-green-500 mr-2"></i>
<span>Morbi tincidunt augue</span>
</li>
<li class="flex items-center mb-4">
<i class="pi pi-check-circle text-green-500 mr-2"></i>
<span>Duis ultricies lacus sed</span>
</li>
<li class="flex items-center mb-4">
<i class="pi pi-check-circle text-green-500 mr-2"></i>
<span>Imperdiet proin</span>
</li>
<li class="flex items-center mb-4">
<i class="pi pi-check-circle text-green-500 mr-2"></i>
<span>Nisi scelerisque</span>
</li>
</ul>
<hr class="mb-4 mx-0 border-t border-0 border-surface" />
<Button label="Buy Now" class="p-4 w-full p-button-outlined"></Button>
</div>
</div>
</div>
</div>
</div>
</BlockViewer>
<BlockViewer header="Call to Action" :code="block4" free>
<div class="bg-surface-0 dark:bg-surface-950 px-6 py-20 md:px-12 lg:px-20">
<div class="text-surface-700 dark:text-surface-100 text-center">
<div class="text-blue-600 font-bold mb-4"><i class="pi pi-discord"></i>&nbsp;POWERED BY DISCORD</div>
<div class="text-surface-900 dark:text-surface-0 font-bold text-5xl mb-4">Join Our Design Community</div>
<div class="text-surface-700 dark:text-surface-100 text-2xl mb-8">Lorem ipsum dolor sit, amet consectetur adipisicing elit. Velit numquam eligendi quos.</div>
<Button label="Join Now" icon="pi pi-discord" class="font-bold px-8 py-4 p-button-raised p-button-rounded whitespace-nowrap"></Button>
</div>
</div>
</BlockViewer>
<BlockViewer header="Banner" :code="block5" containerClass="bg-surface-0 dark:bg-surface-950 py-20" free>
<div class="bg-slate-900 text-gray-100 p-4 flex justify-between lg:justify-center items-center flex-wrap">
<div class="font-bold mr-20">🔥 Hot Deals!</div>
<div class="items-center hidden lg:flex">
<span class="leading-normal">Libero voluptatum atque exercitationem praesentium provident odit.</span>
</div>
<a class="flex items-center ml-2 mr-20">
<a class="text-white" href="#"><span class="underline font-bold">Learn More</span></a>
</a>
<a v-ripple class="flex items-center no-underline justify-center rounded-full text-gray-50 hover:bg-slate-700 cursor-pointer transition-colors duration-150 p-ripple" style="width: 2rem; height: 2rem">
<i class="pi pi-times"></i>
</a>
</div>
</BlockViewer>
<BlockViewer header="Page Heading" :code="block6" free>
<div class="bg-surface-0 dark:bg-surface-950 px-6 py-8 md:px-12 lg:px-20">
<ul class="list-none p-0 m-0 flex items-center font-medium mb-4">
<li>
<a class="text-surface-500 dark:text-surface-300 no-underline leading-normal cursor-pointer">Application</a>
</li>
<li class="px-2">
<i class="pi pi-angle-right text-surface-500 dark:text-surface-300 leading-normal"></i>
</li>
<li>
<span class="text-surface-900 dark:text-surface-0 leading-normal">Analytics</span>
</li>
</ul>
<div class="flex items-start flex-col lg:justify-between lg:flex-row">
<div>
<div class="font-medium text-3xl text-surface-900 dark:text-surface-0">Customers</div>
<div class="flex items-center text-surface-700 dark:text-surface-100 flex-wrap">
<div class="mr-8 flex items-center mt-4">
<i class="pi pi-users mr-2"></i>
<span>332 Active Users</span>
</div>
<div class="mr-8 flex items-center mt-4">
<i class="pi pi-globe mr-2"></i>
<span>9402 Sessions</span>
</div>
<div class="flex items-center mt-4">
<i class="pi pi-clock mr-2"></i>
<span>2.32m Avg. Duration</span>
</div>
</div>
</div>
<div class="mt-4 lg:mt-0">
<Button label="Add" class="p-button-outlined mr-2" icon="pi pi-user-plus"></Button>
<Button label="Save" icon="pi pi-check"></Button>
</div>
</div>
</div>
</BlockViewer>
<BlockViewer header="Stats" :code="block7" free>
<div class="bg-surface-50 dark:bg-surface-950 px-6 py-8 md:px-12 lg:px-20">
<div class="grid grid-cols-12 gap-4">
<div class="col-span-12 md:col-span-6 lg:col-span-3">
<div class="bg-surface-0 dark:bg-surface-900 shadow p-4 rounded-border">
<div class="flex justify-between mb-4">
<div>
<span class="block text-surface-500 dark:text-surface-300 font-medium mb-4">Orders</span>
<div class="text-surface-900 dark:text-surface-0 font-medium text-xl">152</div>
</div>
<div class="flex items-center justify-center bg-blue-100 rounded-border" style="width: 2.5rem; height: 2.5rem">
<i class="pi pi-shopping-cart text-blue-500 text-xl"></i>
</div>
</div>
<span class="text-green-500 font-medium">24 new </span>
<span class="text-surface-500 dark:text-surface-300">since last visit</span>
</div>
</div>
<div class="col-span-12 md:col-span-6 lg:col-span-3">
<div class="bg-surface-0 dark:bg-surface-900 shadow p-4 rounded-border">
<div class="flex justify-between mb-4">
<div>
<span class="block text-surface-500 dark:text-surface-300 font-medium mb-4">Revenue</span>
<div class="text-surface-900 dark:text-surface-0 font-medium text-xl">$2.100</div>
</div>
<div class="flex items-center justify-center bg-orange-100 rounded-border" style="width: 2.5rem; height: 2.5rem">
<i class="pi pi-map-marker text-orange-500 text-xl"></i>
</div>
</div>
<span class="text-green-500 font-medium">%52+ </span>
<span class="text-surface-500 dark:text-surface-300">since last week</span>
</div>
</div>
<div class="col-span-12 md:col-span-6 lg:col-span-3">
<div class="bg-surface-0 dark:bg-surface-900 shadow p-4 rounded-border">
<div class="flex justify-between mb-4">
<div>
<span class="block text-surface-500 dark:text-surface-300 font-medium mb-4">Customers</span>
<div class="text-surface-900 dark:text-surface-0 font-medium text-xl">28441</div>
</div>
<div class="flex items-center justify-center bg-cyan-100 rounded-border" style="width: 2.5rem; height: 2.5rem">
<i class="pi pi-inbox text-cyan-500 text-xl"></i>
</div>
</div>
<span class="text-green-500 font-medium">520 </span>
<span class="text-surface-500 dark:text-surface-300">newly registered</span>
</div>
</div>
<div class="col-span-12 md:col-span-6 lg:col-span-3">
<div class="bg-surface-0 dark:bg-surface-900 shadow p-4 rounded-border">
<div class="flex justify-between mb-4">
<div>
<span class="block text-surface-500 dark:text-surface-300 font-medium mb-4">Comments</span>
<div class="text-surface-900 dark:text-surface-0 font-medium text-xl">152 Unread</div>
</div>
<div class="flex items-center justify-center bg-purple-100 rounded-border" style="width: 2.5rem; height: 2.5rem">
<i class="pi pi-comment text-purple-500 text-xl"></i>
</div>
</div>
<span class="text-green-500 font-medium">85 </span>
<span class="text-surface-500 dark:text-surface-300">responded</span>
</div>
</div>
</div>
</div>
</BlockViewer>
<BlockViewer header="Sign-In" :code="block8" containerClass="bg-surface-50 dark:bg-surface-950 px-6 py-20 md:px-12 lg:px-20 flex items-center justify-center" free>
<div class="bg-surface-0 dark:bg-surface-900 p-6 shadow rounded-border w-full lg:w-6/12">
<div class="text-center mb-8">
<img src="/demo/images/blocks/logos/hyper.svg" alt="Image" height="50" class="mb-4" />
<div class="text-surface-900 dark:text-surface-0 text-3xl font-medium mb-4">Welcome Back</div>
<span class="text-surface-600 dark:text-surface-200 font-medium leading-normal">Don't have an account?</span>
<a class="font-medium no-underline ml-2 text-blue-500 cursor-pointer">Create today!</a>
</div>
<div>
<label for="email1" class="block text-surface-900 dark:text-surface-0 font-medium mb-2">Email</label>
<InputText id="email1" type="text" class="w-full mb-4" />
<label for="password1" class="block text-surface-900 dark:text-surface-0 font-medium mb-2">Password</label>
<InputText id="password1" type="password" class="w-full mb-4" />
<div class="flex items-center justify-between mb-12">
<div class="flex items-center">
<Checkbox id="rememberme1" :binary="true" v-model="checked" class="mr-2"></Checkbox>
<label for="rememberme1">Remember me</label>
</div>
<a class="font-medium no-underline ml-2 text-blue-500 text-right cursor-pointer">Forgot password?</a>
</div>
<Button label="Sign In" icon="pi pi-user" class="w-full"></Button>
</div>
</div>
</BlockViewer>
<BlockViewer header="Description List" :code="block9" containerClass="bg-surface-0 dark:bg-surface-950 px-6 py-20 md:px-12 lg:px-20" free>
<div class="bg-surface-0 dark:bg-surface-950">
<div class="font-medium text-3xl text-surface-900 dark:text-surface-0 mb-4">Movie Information</div>
<div class="text-surface-500 dark:text-surface-300 mb-8">Morbi tristique blandit turpis. In viverra ligula id nulla hendrerit rutrum.</div>
<ul class="list-none p-0 m-0">
<li class="flex items-center py-4 px-2 border-t border-surface flex-wrap">
<div class="text-surface-500 dark:text-surface-300 w-6/12 md:w-2/12 font-medium">Title</div>
<div class="text-surface-900 dark:text-surface-0 w-full md:w-8/12 md:order-none order-1">Heat</div>
<div class="w-6/12 md:w-2/12 flex justify-end">
<Button label="Edit" icon="pi pi-pencil" class="p-button-text"></Button>
</div>
</li>
<li class="flex items-center py-4 px-2 border-t border-surface flex-wrap">
<div class="text-surface-500 dark:text-surface-300 w-6/12 md:w-2/12 font-medium">Genre</div>
<div class="text-surface-900 dark:text-surface-0 w-full md:w-8/12 md:order-none order-1">
<Chip label="Crime" class="mr-2"></Chip>
<Chip label="Drama" class="mr-2"></Chip>
<Chip label="Thriller"></Chip>
</div>
<div class="w-6/12 md:w-2/12 flex justify-end">
<Button label="Edit" icon="pi pi-pencil" class="p-button-text"></Button>
</div>
</li>
<li class="flex items-center py-4 px-2 border-t border-surface flex-wrap">
<div class="text-surface-500 dark:text-surface-300 w-6/12 md:w-2/12 font-medium">Director</div>
<div class="text-surface-900 dark:text-surface-0 w-full md:w-8/12 md:order-none order-1">Michael Mann</div>
<div class="w-6/12 md:w-2/12 flex justify-end">
<Button label="Edit" icon="pi pi-pencil" class="p-button-text"></Button>
</div>
</li>
<li class="flex items-center py-4 px-2 border-t border-surface flex-wrap">
<div class="text-surface-500 dark:text-surface-300 w-6/12 md:w-2/12 font-medium">Actors</div>
<div class="text-surface-900 dark:text-surface-0 w-full md:w-8/12 md:order-none order-1">Robert De Niro, Al Pacino</div>
<div class="w-6/12 md:w-2/12 flex justify-end">
<Button label="Edit" icon="pi pi-pencil" class="p-button-text"></Button>
</div>
</li>
<li class="flex items-center py-4 px-2 border-t border-b border-surface flex-wrap">
<div class="text-surface-500 dark:text-surface-300 w-6/12 md:w-2/12 font-medium">Plot</div>
<div class="text-surface-900 dark:text-surface-0 w-full md:w-8/12 md:order-none order-1 leading-normal">
A group of professional bank robbers start to feel the heat from police when they unknowingly leave a clue at their latest heist.
</div>
<div class="w-6/12 md:w-2/12 flex justify-end">
<Button label="Edit" icon="pi pi-pencil" class="p-button-text"></Button>
</div>
</li>
</ul>
</div>
</BlockViewer>
<BlockViewer header="Card" :code="block10" containerClass="px-6 py-20 md:px-12 lg:px-20" free>
<div class="bg-surface-0 dark:bg-surface-900 p-6 shadow rounded-border">
<div class="text-3xl font-medium text-surface-900 dark:text-surface-0 mb-4">Card Title</div>
<div class="font-medium text-surface-500 dark:text-surface-300 mb-4">Vivamus id nisl interdum, blandit augue sit amet, eleifend mi.</div>
<div style="height: 150px" class="border-2 border-dashed border-surface"></div>
</div>
</BlockViewer>
</div>
</template>

View File

@@ -0,0 +1,65 @@
<template>
<div class="card">
<h3>Documentation</h3>
<p class="bg-primary text-primary-contrast rounded-border p-4">
This page covers the Vite version, for Nuxt 3 visit the <a href="https://github.com/primefaces/sakai-nuxt" class="font-bold bg-primary text-primary-contrast hover:underline">sakai-nuxt</a> repository instead.
</p>
<h5>Getting Started</h5>
<p>
Sakai is an application template for Vue based on the <a href="https://github.com/vuejs/create-vue" class="font-medium text-primary hover:underline">create-vue</a>, the recommended way to start a <strong>Vite-powered</strong> Vue
projects. To get started, clone the <a href="https://github.com/primefaces/sakai-vue" class="font-medium text-primary hover:underline">repository</a> from GitHub and install the dependencies with npm or yarn.
</p>
<pre class="app-code"><code> npm install </code></pre>
<p>or</p>
<pre class="app-code"><code> yarn </code></pre>
<p>Next step is running the application using the serve script and navigate to <i>http://localhost:5173/</i> to view the application. That is it, you may now start with the development of your application using the Sakai template.</p>
<pre class="app-code"><code> npm run dev </code></pre>
<h5>Structure</h5>
<p>Sakai consists of a couple folders, demos and layout have been separated so that you can easily remove what is not necessary for your application.</p>
<ul class="leading-normal">
<li><span class="text-primary font-medium">src/layout</span>: Main layout files, needs to be present</li>
<li><span class="text-primary font-medium">src/views</span>: Demo pages</li>
<li><span class="text-primary font-medium">public/demo</span>: Assets used in demos</li>
<li><span class="text-primary font-medium">public/layout</span>: Assets used in layout</li>
<li><span class="text-primary font-medium">src/assets/demo</span>: Styles used in demos</li>
<li><span class="text-primary font-medium">src/assets/layout</span>: SCSS files of the main layout</li>
</ul>
<h5>Menu</h5>
<p>Main menu is defined at <span class="text-primary font-medium">src/layout/AppMenu.vue</span> file.</p>
<h5>Integration with Existing Vite Applications</h5>
<p>Only the folders that are related to the layout needs to move in to your project. We've created a short tutorial with details.</p>
<div class="video-container">
<iframe className="video" width="560" height="315" src="https://www.youtube.com/embed/AHeSjJFR3ZE" frameborder="0" allowfullscreen></iframe>
</div>
<h5>PrimeVue Theme</h5>
<p>Sakai theming is based on the PrimeVue theme being used. Default theme is <b>lara-light-indigo</b>.</p>
</div>
</template>
<style lang="scss" scoped>
@media screen and (max-width: 991px) {
.video-container {
position: relative;
width: 100%;
height: 0;
padding-bottom: 56.25%;
iframe {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
}
}
</style>

View File

@@ -0,0 +1,91 @@
<script setup>
import { ref, onMounted, computed } from 'vue';
const icons = ref(null);
const filter = ref(null);
const filteredIcons = computed(() => {
if (filter.value) return icons.value.filter((icon) => icon.properties.name.indexOf(filter.value.toLowerCase()) > -1);
else return icons.value;
});
onMounted(() => {
fetch('/demo/data/icons.json', { headers: { 'Cache-Control': 'no-cache' } })
.then((res) => res.json())
.then((d) => {
let data = d.icons.filter((value) => {
return value.icon.tags.indexOf('deprecate') === -1;
});
data.sort((icon1, icon2) => {
if (icon1.properties.name < icon2.properties.name) return -1;
else if (icon1.properties.name > icon2.properties.name) return 1;
else return 0;
});
icons.value = data;
});
});
</script>
<template>
<div class="card">
<h2>Icons</h2>
<p>
PrimeVue components internally use <a href="https://github.com/primefaces/primeicons" class="font-medium text-primary hover:underline">PrimeIcons</a> library, the official icons suite from
<a href="https://www.primetek.com.tr" class="font-medium text-primary hover:underline">PrimeTek</a>.
</p>
<h4>Download</h4>
<p>PrimeIcons is available at npm, run the following command to download it to your project.</p>
<pre class="app-code"><code>npm install primeicons --save</code></pre>
<h4>Getting Started</h4>
<p>PrimeIcons use the <strong>pi pi-&#123;icon&#125;</strong> syntax such as <strong>pi pi-check</strong>. A standalone icon can be displayed using an element like <i>i</i> or <i>span</i></p>
<pre class="app-code"><code>&lt;i class="pi pi-check"&gt;&lt;/i&gt;
&lt;i class="pi pi-times"&gt;&lt;/i&gt;</code></pre>
<i class="pi pi-check" style="margin-right: 0.5rem"></i>
<i class="pi pi-times"></i>
<h4>Size</h4>
<p>Size of the icons can easily be changed using font-size property.</p>
<pre class="app-code"><code>&lt;i class="pi pi-check"&gt;&lt;/i&gt;</code></pre>
<i class="pi pi-check"></i>
<pre class="app-code"><code>&lt;i class="pi pi-check" style="font-size: 2rem"&gt;&lt;/i&gt;</code></pre>
<i class="pi pi-check" style="font-size: 2rem"></i>
<h4>Spinning Animation</h4>
<p>Special pi-spin class applies continuous rotation to an icon.</p>
<pre class="app-code"><code>&lt;i class="pi pi-spin pi-spinner" style="font-size: 2rem"&gt;&lt;/i&gt;</code></pre>
<i class="pi pi-spin pi-spinner" style="font-size: 2rem"></i>
<h4>List of Icons</h4>
<p>
Here is the current list of PrimeIcons, more icons are added periodically. You may also <a href="https://github.com/primefaces/primeicons/issues" class="font-medium text-primary hover:underline">request new icons</a> at the issue tracker.
</p>
<InputText v-model="filter" class="w-full p-4 mt-4 mb-8" placeholder="Search an icon" />
<div class="grid grid-cols-12 gap-4 icons-list text-center">
<div class="col-span-6 sm:col-span-4 lg:col-span-3 xl:col-span-2 pb-8" v-for="icon of filteredIcons" :key="icon.properties.name">
<i :class="'text-2xl mb-2 pi pi-' + icon.properties.name"></i>
<div>pi-{{ icon.properties.name }}</div>
</div>
</div>
</div>
</template>
<style lang="scss" scoped>
.icons-list {
i {
color: var(--text-color-secondary);
}
}
</style>