TimeTrex Community Edition v16.2.0

This commit is contained in:
2022-12-13 07:10:06 +01:00
commit 472f000c1b
6810 changed files with 2636142 additions and 0 deletions

View File

@@ -0,0 +1,30 @@
<template>
<div class="exception-body access-body">
<div class="exception-container">
<img :src="'assets/layout/images/logo-' + logoColor + '.png'" alt="apollo-layout"/>
<h1>Denied</h1>
<p>
You do not have the necessary privileges.
</p>
<router-link to="/">
<Button label="Go To Dashboard" icon="pi pi-arrow-left" />
</router-link>
</div>
</div>
</template>
<script>
export default {
computed: {
logoColor() {
if (this.$appState.colorScheme === 'light')
return 'dark';
else return 'white';
}
}
}
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,118 @@
<template>
<div class="p-grid">
<div class="p-col-12">
<div class="card">
<FullCalendar :events="events" :options="options" />
<Dialog v-model:visible="eventDialog" :style="{width: '450px'}" header="Event Details" :modal="true" :closable="true">
<div class="p-fluid">
<div class="p-field">
<label for="title">Title</label>
<InputText id="title" v-if="clickedEvent" v-model="changedEvent.title" required="true" autofocus/>
</div>
<div class="p-field">
<label for="start">From</label>
<Calendar id="start" v-if="clickedEvent" v-model="changedEvent.start" :showTime="true" appendTo="body"/>
</div>
<div class="p-field">
<label for="end">To</label>
<Calendar id="end" v-if="clickedEvent" v-model="changedEvent.end" :showTime="true" appendTo="body"/>
</div>
<div class="p-field-checkbox">
<Checkbox id="allday" name="allday" value="All Day" v-model="changedEvent.allDay" />
<label for="allday">All Day</label>
</div>
</div>
<template #footer>
<Button label="Save" icon="pi pi-check" class="p-button-text" @click="save"/>
<Button label="Reset" icon="pi pi-refresh" class="p-button-text" @click="reset" />
</template>
</Dialog>
</div>
</div>
</div>
</template>
<script>
import EventService from '../service/EventService';
import dayGridPlugin from '@fullcalendar/daygrid';
import timeGridPlugin from '@fullcalendar/timegrid';
import interactionPlugin from '@fullcalendar/interaction';
export default {
data() {
return {
eventDialog: false,
clickedEvent: null,
changedEvent: {title:'', start: null, end:'', allDay: null},
options: {
plugins:[dayGridPlugin, timeGridPlugin, interactionPlugin],
initialDate : '2023-01-01',
headerToolbar: {
left: 'prev,next today',
center: 'title',
right: 'dayGridMonth,timeGridWeek,timeGridDay'
},
editable: true,
selectable:true,
selectMirror: true,
dayMaxEvents: true,
eventClick: (e) => {
this.eventDialog = true;
this.clickedEvent = e.event;
this.changedEvent.title = this.clickedEvent.title;
this.changedEvent.start = this.clickedEvent.start;
this.changedEvent.end = this.clickedEvent.end;
}
},
events: null
};
},
eventService: null,
created() {
this.eventService = new EventService();
},
mounted() {
this.eventService.getEvents().then(data => this.events = data);
},
methods: {
findIndexById(id) {
let index = -1;
for (let i = 0; i < this.events.length; i++) {
if (this.events[i].id === id) {
index = i;
break;
}
}
return index;
},
save() {
this.eventDialog = false;
this.clickedEvent.setProp('title', this.changedEvent.title)
this.clickedEvent.setStart(this.changedEvent.start)
this.clickedEvent.setEnd(this.changedEvent.end)
this.clickedEvent.setAllDay(this.changedEvent.allDay)
this.changedEvent = {title:'', start: null, end:'', allDay: null};
},
reset() {
this.changedEvent.title = this.clickedEvent.title;
this.changedEvent.start = this.clickedEvent.start;
this.changedEvent.end = this.clickedEvent.end;
}
}
}
</script>
<style scoped>
@media screen and (max-width: 960px) {
::v-deep(.fc-header-toolbar) {
display: flex;
flex-wrap: wrap;
}
}
</style>

View File

@@ -0,0 +1,350 @@
<template>
<div class="p-grid crud-demo">
<div class="p-col-12">
<div class="card">
<Toast/>
<Toolbar class="p-mb-4">
<template v-slot:left>
<Button label="New" icon="pi pi-plus" class="p-button-success p-mr-2" @click="openNew" />
<Button label="Delete" icon="pi pi-trash" class="p-button-danger" @click="confirmDeleteSelected" :disabled="!selectedProducts || !selectedProducts.length" />
</template>
<template v-slot:right>
<FileUpload mode="basic" accept="image/*" :maxFileSize="1000000" label="Import" chooseLabel="Import" class="p-mr-2 p-d-inline-block" />
<Button label="Export" icon="pi pi-upload" class="p-button-help" @click="exportCSV($event)" />
</template>
</Toolbar>
<DataTable ref="dt" :value="products" v-model:selection="selectedProducts" dataKey="id" :paginator="true" :rows="10" :filters="filters"
paginatorTemplate="FirstPageLink PrevPageLink PageLinks NextPageLink LastPageLink CurrentPageReport RowsPerPageDropdown" :rowsPerPageOptions="[5,10,25]"
currentPageReportTemplate="Showing {first} to {last} of {totalRecords} products" responsiveLayout="scroll">
<template #header>
<div class="table-header p-d-flex p-flex-column p-flex-md-row p-jc-md-between p-ai-start p-ai-md-center">
<h5 class="p-mb-2 p-m-md-0">Manage Products</h5>
<span class="p-input-icon-left">
<i class="pi pi-search" />
<InputText v-model="filters['global'].value" placeholder="Search..." />
</span>
</div>
</template>
<Column selectionMode="multiple" headerStyle="width: 3rem"></Column>
<Column field="code" header="Code" :sortable="true">
<template #body="slotProps">
<span class="p-column-title">Code</span>
{{slotProps.data.code}}
</template>
</Column>
<Column field="name" header="Name" :sortable="true">
<template #body="slotProps">
<span class="p-column-title">Name</span>
{{slotProps.data.name}}
</template>
</Column>
<Column header="Image">
<template #body="slotProps">
<span class="p-column-title">Image</span>
<img :src="'assets/demo/images/product/' + slotProps.data.image" :alt="slotProps.data.image" class="product-image" />
</template>
</Column>
<Column field="price" header="Price" :sortable="true">
<template #body="slotProps">
<span class="p-column-title">Price</span>
{{formatCurrency(slotProps.data.price)}}
</template>
</Column>
<Column field="category" header="Category" :sortable="true">
<template #body="slotProps">
<span class="p-column-title">Category</span>
{{formatCurrency(slotProps.data.category)}}
</template>
</Column>
<Column field="rating" header="Reviews" :sortable="true">
<template #body="slotProps">
<span class="p-column-title">Rating</span>
<Rating :modelValue="slotProps.data.rating" :readonly="true" :cancel="false" />
</template>
</Column>
<Column field="inventoryStatus" header="Status" :sortable="true">
<template #body="slotProps">
<span class="p-column-title">Status</span>
<span :class="'product-badge status-' + (slotProps.data.inventoryStatus ? slotProps.data.inventoryStatus.toLowerCase() : '')">{{slotProps.data.inventoryStatus}}</span>
</template>
</Column>
<Column>
<template #body="slotProps">
<Button icon="pi pi-pencil" class="p-button-rounded p-button-success p-mr-2" @click="editProduct(slotProps.data)" />
<Button icon="pi pi-trash" class="p-button-rounded p-button-warning" @click="confirmDeleteProduct(slotProps.data)" />
</template>
</Column>
</DataTable>
<Dialog v-model:visible="productDialog" :style="{width: '450px'}" header="Product Details" :modal="true" class="p-fluid">
<img :src="'assets/demo/images/product/' + product.image" :alt="product.image" class="product-image" v-if="product.image" />
<div class="p-field">
<label for="name">Name</label>
<InputText id="name" v-model.trim="product.name" required="true" autofocus :class="{'p-invalid': submitted && !product.name}" />
<small class="p-invalid" v-if="submitted && !product.name">Name is required.</small>
</div>
<div class="p-field">
<label for="description">Description</label>
<Textarea id="description" v-model="product.description" required="true" rows="3" cols="20" />
</div>
<div class="p-field">
<label for="inventoryStatus" class="p-mb-3">Inventory Status</label>
<Dropdown id="inventoryStatus" v-model="product.inventoryStatus" :options="statuses" optionLabel="label" placeholder="Select a Status">
<template #value="slotProps">
<div v-if="slotProps.value && slotProps.value.value">
<span :class="'product-badge status-' +slotProps.value.value">{{slotProps.value.label}}</span>
</div>
<div v-else-if="slotProps.value && !slotProps.value.value">
<span :class="'product-badge status-' +slotProps.value.toLowerCase()">{{slotProps.value}}</span>
</div>
<span v-else>
{{slotProps.placeholder}}
</span>
</template>
</Dropdown>
</div>
<div class="p-field">
<label class="p-mb-3">Category</label>
<div class="p-formgrid p-grid">
<div class="p-field-radiobutton p-col-6">
<RadioButton id="category1" name="category" value="Accessories" v-model="product.category" />
<label for="category1">Accessories</label>
</div>
<div class="p-field-radiobutton p-col-6">
<RadioButton id="category2" name="category" value="Clothing" v-model="product.category" />
<label for="category2">Clothing</label>
</div>
<div class="p-field-radiobutton p-col-6">
<RadioButton id="category3" name="category" value="Electronics" v-model="product.category" />
<label for="category3">Electronics</label>
</div>
<div class="p-field-radiobutton p-col-6">
<RadioButton id="category4" name="category" value="Fitness" v-model="product.category" />
<label for="category4">Fitness</label>
</div>
</div>
</div>
<div class="p-formgrid p-grid">
<div class="p-field p-col">
<label for="price">Price</label>
<InputNumber id="price" v-model="product.price" mode="currency" currency="USD" locale="en-US" />
</div>
<div class="p-field p-col">
<label for="quantity">Quantity</label>
<InputNumber id="quantity" v-model="product.quantity" integeronly />
</div>
</div>
<template #footer>
<Button label="Cancel" icon="pi pi-times" class="p-button-text" @click="hideDialog"/>
<Button label="Save" icon="pi pi-check" class="p-button-text" @click="saveProduct" />
</template>
</Dialog>
<Dialog v-model:visible="deleteProductDialog" :style="{width: '450px'}" header="Confirm" :modal="true">
<div class="confirmation-content">
<i class="pi pi-exclamation-triangle p-mr-3" style="font-size: 2rem" />
<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" class="p-button-text" @click="deleteProductDialog = false"/>
<Button label="Yes" icon="pi pi-check" class="p-button-text" @click="deleteProduct" />
</template>
</Dialog>
<Dialog v-model:visible="deleteProductsDialog" :style="{width: '450px'}" header="Confirm" :modal="true">
<div class="confirmation-content">
<i class="pi pi-exclamation-triangle p-mr-3" style="font-size: 2rem" />
<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" class="p-button-text" @click="deleteProductsDialog = false"/>
<Button label="Yes" icon="pi pi-check" class="p-button-text" @click="deleteSelectedProducts" />
</template>
</Dialog>
</div>
</div>
</div>
</template>
<script>
import {FilterMatchMode} from 'primevue/api';
import ProductService from '../service/ProductService';
export default {
data() {
return {
products: null,
productDialog: false,
deleteProductDialog: false,
deleteProductsDialog: false,
product: {},
selectedProducts: null,
filters: {},
submitted: false,
statuses: [
{label: 'INSTOCK', value: 'instock'},
{label: 'LOWSTOCK', value: 'lowstock'},
{label: 'OUTOFSTOCK', value: 'outofstock'}
]
}
},
productService: null,
created() {
this.productService = new ProductService();
this.initFilters();
},
mounted() {
this.productService.getProducts().then(data => this.products = data);
},
methods: {
formatCurrency(value) {
if(value)
return value.toLocaleString('en-US', {style: 'currency', currency: 'USD'});
return;
},
openNew() {
this.product = {};
this.submitted = false;
this.productDialog = true;
},
hideDialog() {
this.productDialog = false;
this.submitted = false;
},
saveProduct() {
this.submitted = true;
if (this.product.name.trim()) {
if (this.product.id) {
this.product.inventoryStatus = this.product.inventoryStatus.value ? this.product.inventoryStatus.value: this.product.inventoryStatus;
this.products[this.findIndexById(this.product.id)] = this.product;
this.$toast.add({severity:'success', summary: 'Successful', detail: 'Product Updated', life: 3000});
}
else {
this.product.id = this.createId();
this.product.code = this.createId();
this.product.image = 'product-placeholder.svg';
this.product.inventoryStatus = this.product.inventoryStatus ? this.product.inventoryStatus.value : 'INSTOCK';
this.products.push(this.product);
this.$toast.add({severity:'success', summary: 'Successful', detail: 'Product Created', life: 3000});
}
this.productDialog = false;
this.product = {};
}
},
editProduct(product) {
this.product = {...product};
this.productDialog = true;
},
confirmDeleteProduct(product) {
this.product = product;
this.deleteProductDialog = true;
},
deleteProduct() {
this.products = this.products.filter(val => val.id !== this.product.id);
this.deleteProductDialog = false;
this.product = {};
this.$toast.add({severity:'success', summary: 'Successful', detail: 'Product Deleted', life: 3000});
},
findIndexById(id) {
let index = -1;
for (let i = 0; i < this.products.length; i++) {
if (this.products[i].id === id) {
index = i;
break;
}
}
return index;
},
createId() {
let id = '';
var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
for ( var i = 0; i < 5; i++ ) {
id += chars.charAt(Math.floor(Math.random() * chars.length));
}
return id;
},
exportCSV() {
this.$refs.dt.exportCSV();
},
confirmDeleteSelected() {
this.deleteProductsDialog = true;
},
deleteSelectedProducts() {
this.products = this.products.filter(val => !this.selectedProducts.includes(val));
this.deleteProductsDialog = false;
this.selectedProducts = null;
this.$toast.add({severity:'success', summary: 'Successful', detail: 'Products Deleted', life: 3000});
},
initFilters() {
this.filters = {
'global': {value: null, matchMode: FilterMatchMode.CONTAINS},
}
}
}
}
</script>
<style scoped lang="scss">
.table-header {
display: flex;
justify-content: space-between;
}
.product-image {
width: 100px;
box-shadow: 0 3px 6px rgba(0, 0, 0, 0.16), 0 3px 6px rgba(0, 0, 0, 0.23);
}
.p-dialog .product-image {
width: 150px;
margin: 0 auto 2rem auto;
display: block;
}
.confirmation-content {
display: flex;
align-items: center;
justify-content: center;
}
.product-badge {
border-radius: 2px;
padding: .25em .5rem;
text-transform: uppercase;
font-weight: 700;
font-size: 12px;
letter-spacing: .3px;
&.status-instock {
background: #C8E6C9;
color: #256029;
}
&.status-outofstock {
background: #FFCDD2;
color: #C63737;
}
&.status-lowstock {
background: #FEEDAF;
color: #8A5340;
}
}
@media screen and (max-width: 960px) {
::v-deep(.p-toolbar) {
flex-wrap: wrap;
.p-button {
margin-bottom: 0.25rem;
}
}
}
</style>

View File

@@ -0,0 +1,31 @@
<template>
<div class="exception-body error-body">
<div class="exception-container">
<img :src="'assets/layout/images/logo-' + logoColor + '.png'" alt="apollo-layout"/>
<h1>Error</h1>
<p>
Please contact the system administrator.
</p>
<router-link to="/">
<Button label="Go To Dashboard" icon="pi pi-arrow-left" />
</router-link>
</div>
</div>
</template>
<script>
export default {
computed: {
logoColor() {
if (this.$appState.colorScheme === 'light')
return 'dark';
else return 'white';
}
}
}
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,146 @@
<template>
<div class="p-grid help-page">
<div class="p-col-12">
<div class="card help-search">
<div class="help-search-content">
<h1>We are here to help</h1>
<div class="search-container">
<i class="pi pi-search"></i>
<InputText type="text" placeholder="Search" />
</div>
</div>
</div>
</div>
<div class="p-col-12 p-lg-6">
<div class="card">
<h4>General</h4>
<Accordion :activeIndex="0">
<AccordionTab header="Header I">
<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. 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>
</AccordionTab>
<AccordionTab header="Header II">
<p>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>
</AccordionTab>
<AccordionTab header="Header III">
<p>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>
</AccordionTab>
</Accordion>
<h4>FAQ</h4>
<Accordion :activeIndex="0">
<AccordionTab header="FAQ I">
<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. 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>
</AccordionTab>
<AccordionTab header="FAQ II">
<p>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>
</AccordionTab>
<AccordionTab header="FAQ III">
<p>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>
</AccordionTab>
</Accordion>
</div>
</div>
<div class="p-col-12 p-lg-6">
<div class="card">
<h4>System Status</h4>
<p>All services are operational.</p>
<div class="status-bars">
<div class="status-bar"></div>
<div class="status-bar"></div>
<div class="status-bar"></div>
<div class="status-bar"></div>
<div class="status-bar"></div>
<div class="status-bar"></div>
<div class="status-bar"></div>
<div class="status-bar"></div>
<div class="status-bar status-bar-failure"></div>
<div class="status-bar"></div>
<div class="status-bar"></div>
<div class="status-bar"></div>
<div class="status-bar"></div>
<div class="status-bar"></div>
<div class="status-bar"></div>
<div class="status-bar"></div>
<div class="status-bar"></div>
<div class="status-bar"></div>
<div class="status-bar"></div>
<div class="status-bar"></div>
<div class="status-bar"></div>
<div class="status-bar"></div>
<div class="status-bar"></div>
<div class="status-bar"></div>
<div class="status-bar"></div>
<div class="status-bar"></div>
<div class="status-bar"></div>
<div class="status-bar"></div>
<div class="status-bar"></div>
<div class="status-bar"></div>
</div>
<div class="status-bar-footer">
<span>30 Days Ago</span>
<span>Today</span>
</div>
</div>
<div class="card">
<h4>Articles</h4>
<p>Recent articles from our team.</p>
<div class="blog-posts">
<div class="blog-post">
<div class="blog-text">
<h1>Building Revenue With Confidence</h1>
<span>And avoiding failures</span>
</div>
<div class="blog-profile">
<img src="assets/demo/images/avatar/amyelsner.png" alt="apollo" />
</div>
</div>
<div class="blog-post">
<div class="blog-text">
<h1>Latest Marketing Trends</h1>
<span>Don't miss out our tips</span>
</div>
<div class="blog-profile">
<img src="assets/demo/images/avatar/annafali.png" alt="apollo" />
</div>
</div>
<div class="blog-post">
<div class="blog-text">
<h1>How To Reach Your Audience</h1>
<span>10 ways to increase your efficiency</span>
</div>
<div class="blog-profile">
<img src="assets/demo/images/avatar/stephenshaw.png" alt="apollo" />
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
}
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,117 @@
<template>
<div>
<Button label="Print" icon="pi pi-print" @click="printClick" style="display: block; margin-bottom: 20px; margin-left: 6px" :key="1"></Button>
<div class="p-grid">
<div class="p-col">
<div class="card" >
<div id="invoice-content">
<div class="invoice">
<div class="invoice-header">
<div class="invoice-company">
<img id="invoice-logo" class="logo-image" :src="'assets/layout/images/logo-' + logoColor + '.png'" alt="apollo-layout" />
<div class="company-name">YOUR COMPANY</div>
<div>9137 3rd Lane California City</div>
<div>CA 93504, U.S.A.</div>
</div>
<div>
<div class="invoice-title">INVOICE</div>
<div class="invoice-details">
<div class="invoice-label">DATE</div>
<div class="invoice-value">{{new Date().toISOString().split('T')[0]}}</div>
<div class="invoice-label">INVOICE #</div>
<div class="invoice-value">8523</div>
<div class="invoice-label">CUSTOMER ID</div>
<div class="invoice-value">C1613</div>
</div>
</div>
</div>
<div class="invoice-to">
<div class="bill-to">BILL TO</div>
<div class="invoice-to-info">
<div>Claire Williams, 148 Hope Lane</div>
<div>Palo Alto, CA 94304. </div>
</div>
</div>
<div class="invoice-items">
<table>
<thead>
<tr>
<th>Description</th>
<th>Quantity</th>
<th>Unit Price</th>
<th>Line Total</th>
</tr>
</thead>
<tbody>
<tr>
<td>Green T-Shirt</td>
<td>1</td>
<td>$49.00</td>
<td>$49.00</td>
</tr>
<tr>
<td>Game Controller</td>
<td>2</td>
<td>$99.00</td>
<td>$198.00</td>
</tr>
<tr>
<td>Mini Speakers</td>
<td>1</td>
<td>$85.00</td>
<td>$85.00</td>
</tr>
</tbody>
</table>
</div>
<div class="invoice-summary">
<div class="invoice-notes">
<b>NOTES</b>
<div>
</div>
</div>
<div>
<div class="invoice-details">
<div class="invoice-label">SUBTOTAL</div>
<div class="invoice-value">$332.00</div>
<div class="invoice-label">VAT</div>
<div class="invoice-value">0</div>
<div class="invoice-label">TOTAL</div>
<div class="invoice-value">$332.00</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
methods: {
printClick() {
window.print();
}
},
computed: {
logoColor() {
if (this.$appState.colorScheme === 'light')
return 'dark';
else return 'white';
}
}
}
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,55 @@
<template>
<div class="login-body">
<div class="body-container">
<div class="p-grid">
<div class="p-col-12 p-lg-6 left-side">
<img :src="'assets/layout/images/logo-' + logoColor + '.png'" alt="apollo-layout"/>
<h1>Welcome</h1>
<p>
Sign in to start your session
</p>
</div>
<div class="p-col-12 p-lg-6 right-side">
<div class="login-wrapper">
<div class="login-container">
<span class="title">Login</span>
<div class="p-grid p-fluid">
<div class="p-col-12">
<InputText placeholder="Username"/>
</div>
<div class="p-col-12">
<InputText type="password" placeholder="Password"/>
</div>
<div class="p-col-6">
<router-link to="/">
<Button label="Sign In" icon="pi pi-check"/>
</router-link>
</div>
<div class="p-col-6 password-container">
<button class="p-link">Forgot Password?</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
computed: {
logoColor() {
if (this.$appState.colorScheme === 'light')
return 'dark';
else return 'white';
}
}
}
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,31 @@
<template>
<div class="exception-body notfound-body">
<div class="exception-container">
<img :src="'assets/layout/images/logo-' + logoColor + '.png'" alt="apollo-layout"/>
<h1>Not Found</h1>
<p>
Resource is not found.
</p>
<router-link to="/">
<Button label="Go To Dashboard" icon="pi pi-arrow-left" />
</router-link>
</div>
</div>
</template>
<script>
export default {
computed: {
logoColor() {
if (this.$appState.colorScheme === 'light')
return 'dark';
else return 'white';
}
}
}
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,126 @@
<template>
<div class="p-grid">
<div class="p-col-12">
<div class="card">
<h4>Timeline</h4>
<h5>Custom Timeline</h5>
<Timeline :value="customEvents" align="alternate" class="customized-timeline">
<template #marker="slotProps">
<span class="custom-marker p-shadow-2" :style="{backgroundColor: slotProps.item.color}">
<i :class="slotProps.item.icon"></i>
</span>
</template>
<template #content="slotProps">
<Card>
<template #title>
{{slotProps.item.status}}
</template>
<template #subtitle>
{{slotProps.item.date}}
</template>
<template #content>
<img v-if="slotProps.item.image" :src="'assets/demo/images/product/' + slotProps.item.image" :alt="slotProps.item.name" width="200" class="p-shadow-2" />
<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" class="p-button-text"></Button>
</template>
</Card>
</template>
</Timeline>
<h5 style="margin-top: 5em">Horizontal - Alternate Align</h5>
<Timeline :value="horizontalEvents" layout="horizontal" align="alternate">
<template #content="slotProps">
{{slotProps.item}}
</template>
<template #opposite>
&nbsp;
</template>
</Timeline>
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
customEvents: [
{
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'
}
],
horizontalEvents: [
'2020', '2021', '2022', '2023'
]
}
}
}
</script>
<style lang="scss" scoped>
.custom-marker {
display: flex;
width: 2rem;
height: 2rem;
align-items: center;
justify-content: center;
color: #ffffff;
border-radius: 50%;
z-index: 1;
}
::v-deep(.p-button) {
min-width: 8em;
}
::v-deep(.p-timeline-event-content) {
line-height: 1;
}
::v-deep(.p-timeline-event-opposite) {
line-height: 1;
}
@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>