split up routes + setup

This commit is contained in:
2023-04-23 15:50:52 +02:00
parent 8d751026b6
commit 5e406e99d6
19 changed files with 765 additions and 240 deletions

View File

@@ -22,6 +22,7 @@
--hover-color: rgb(165, 165, 165); --hover-color: rgb(165, 165, 165);
--accent-background-hover: #4380a8; --accent-background-hover: #4380a8;
--overlay-color: rgba(37, 37, 37, 0.575); --overlay-color: rgba(37, 37, 37, 0.575);
--inactive-color: rgb(100, 100, 100);
} }
:root.dark { :root.dark {
@@ -32,6 +33,7 @@
--accent-color: #42b983; --accent-color: #42b983;
--hover-color: rgb(165, 165, 165); --hover-color: rgb(165, 165, 165);
--accent-background-hover: #4380a8; --accent-background-hover: #4380a8;
--inactive-color: rgb(190, 190, 190);
} }
@media ( prefers-color-scheme: dark ) { @media ( prefers-color-scheme: dark ) {
@@ -43,6 +45,7 @@
--accent-color: #42b983; --accent-color: #42b983;
--hover-color: rgb(165, 165, 165); --hover-color: rgb(165, 165, 165);
--accent-background-hover: #4380a8; --accent-background-hover: #4380a8;
--inactive-color: rgb(190, 190, 190);
} }
} }

View File

@@ -22,7 +22,7 @@
}, },
methods: { methods: {
setup () { setup () {
this.$router.push( '/setup' );
} }
}, },
} }

View File

@@ -0,0 +1,331 @@
<template>
<div class="seatingWrapper">
<div class="sidebar">
<h2>{{ eventInfo.name }}</h2>
<h3>{{ eventInfo.date }}</h3>
<h3>{{ eventInfo.location }}</h3>
<h3>Selected tickets</h3>
<table class="price-table" v-for="event in selectedSeats">
<tr>
<h4>{{ event.name }}</h4>
</tr>
<tr v-for="ticket in event.selectedSeats">
<td>{{ seating[ ticket[ 'row' ] ][ 'content' ][ ticket[ 'seat' ] ][ 'name' ] }} ({{ eventInfo[ 'ageGroups' ][ ticket[ 'categoryID' ] ][ 'name' ] }})</td>
<td>{{ eventInfo[ 'currency' ] }} {{ ticket[ 'price' ] }}</td>
</tr>
</table>
<h3>Total: {{ eventInfo[ 'currency' ] }} {{ total }}</h3>
<router-link to="/cart">To cart</router-link>
</div>
<div class="seatingPlan">
<h3>Available tickets</h3>
<div v-for="ticket in tickets">
{{ ticket }}
</div>
</div>
<div class="overlay" id="placeNotAvailable">
<div class="popup">
<div class="popup-content">
<div class="close-container">
<span class="material-symbols-outlined close-button" @click="closePlaceNotAvailablePopup()">close</span>
</div>
<div class="popup-content-wrapper">
<h3>One or more seat(s) you have previously selected is/are no longer available!</h3>
<p>Please select another one!</p>
<button class="button" @click="closePlaceNotAvailablePopup()">Ok</button>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'noseatplan',
props: {
ticketID: String
},
data () {
return {
tickets: {},
eventInfo: { 'name': 'TestEvent', 'location': 'TestLocation', 'date': 'TestDate', 'RoomName': 'TestRoom', 'currency': 'CHF', 'categories': { '1': { 'price': { '1':25, '2':35 }, 'bg': 'black', 'fg': 'white', 'name': 'Category 1' }, '2': { 'price': { '1':15, '2':20 }, 'bg': 'green', 'fg': 'white', 'name': 'Category 2' } }, 'ageGroups': { '1':{ 'id': 1, 'name':'Child', 'age':'0 - 15.99' }, '2':{ 'id': 2, 'name': 'Adult', 'age': null } }, 'ageGroupCount':2, 'stage': true },
selectedSeats: {},
pricingCurrentlySelected: {},
total: 0,
}
},
methods: {
loadPreviouslySelected () {
/*
This function is called whenever the data on the webpage is to be reloaded
*/
// load data from cart and set up cart if not available
let cart = sessionStorage.getItem( 'cart' ) ? JSON.parse( sessionStorage.getItem( 'cart' ) ) : {};
cart[ this.ticketID ?? 'default' ] = cart[ this.ticketID ?? 'default' ] ? cart[ this.ticketID ?? 'default' ] : { 'name': this.eventInfo.name, 'date': this.eventInfo.date, 'location': this.eventInfo.location, 'currency': this.eventInfo.currency };
cart[ this.ticketID ?? 'default' ][ 'selectedSeats' ] = cart[ this.ticketID ?? 'default' ][ 'selectedSeats' ] ? cart[ this.ticketID ?? 'default' ][ 'selectedSeats' ] : {};
let data = cart[ this.ticketID ?? 'default' ][ 'selectedSeats' ] ? cart[ this.ticketID ?? 'default' ][ 'selectedSeats' ] : {};
let showError = false
for ( let i in data ) {
if ( this.seating[ data[ i ][ 'row' ] ][ 'content' ][ data[ i ][ 'seat' ] ][ 'available' ] ) {
this.seating[ data[ i ][ 'row' ] ][ 'content' ][ data[ i ][ 'seat' ] ][ 'selected' ] = true;
} else {
showError = true;
delete data[ i ];
}
}
if ( showError ) {
setTimeout( function () {
$( '#placeNotAvailable' ).show( 200 );
console.log( 'showing error message' );
}, 500 );
}
cart[ this.ticketID ?? 'default' ][ 'selectedSeats' ] = data;
sessionStorage.setItem( 'cart', JSON.stringify( cart ) );
this.selectedSeats = cart;
this.sumUp();
},
sumUp () {
// This function calculates the total price of the tickets for this event.
let cart = sessionStorage.getItem( 'cart' ) ? JSON.parse( sessionStorage.getItem( 'cart' ) ) : {};
let price = 0;
for ( let i in cart ) {
for ( let entry in cart[ i ][ 'selectedSeats' ] ) {
price += parseInt( cart[ i ][ 'selectedSeats' ][ entry ][ 'price' ] );
}
}
let back = {};
back[ 'total' ] = price;
back[ 'currency' ] = this.eventInfo.currency;
sessionStorage.setItem( 'backend', JSON.stringify( back ) );
this.total = price;
sessionStorage.setItem( 'cart', JSON.stringify( cart ) );
},
closePlaceNotAvailablePopup () {
$( '#placeNotAvailable' ).hide( 300 );
},
selectSeat( placeID, rowID ) {
/*
This function allows the user to select a seat and deselect it, if it has previously
been selected.
*/
sessionStorage.setItem( 'tempStorage', JSON.stringify( { 1:[ placeID, rowID ] } ) );
let cart = sessionStorage.getItem( 'cart' ) ? JSON.parse( sessionStorage.getItem( 'cart' ) ) : {};
cart[ this.ticketID ?? 'default' ] = cart[ this.ticketID ?? 'default' ] ? cart[ this.ticketID ?? 'default' ] : {};
cart[ this.ticketID ?? 'default' ][ 'selectedSeats' ] = cart[ this.ticketID ?? 'default' ][ 'selectedSeats' ] ? cart[ this.ticketID ?? 'default' ][ 'selectedSeats' ] : {};
let data = cart[ this.ticketID ?? 'default' ][ 'selectedSeats' ] ? cart[ this.ticketID ?? 'default' ][ 'selectedSeats' ] : {};
let isDeleting = false;
for ( let i in data ) {
if ( data[ i ][ 'seat' ] == placeID && data[ i ][ 'row' ] == rowID ) {
delete data[ i ];
isDeleting = true;
}
}
this.seating[ rowID ][ 'content' ][ placeID ][ 'selected' ] = !isDeleting;
if ( isDeleting ) {
cart[ this.ticketID ?? 'default' ][ 'selectedSeats' ] = data;
sessionStorage.setItem( 'cart', JSON.stringify( cart ) );
this.selectedSeats = cart;
this.sumUp();
} else {
if ( this.eventInfo.ageGroupCount > 1 ) {
$( '#overlay' ).show( 200 );
} else {
this.storeSeat( '1' );
}
}
this.pricingCurrentlySelected = this.eventInfo[ 'categories' ][ this.seating[ rowID ][ 'content' ][ placeID ][ 'category' ] ][ 'price' ];
},
closePopup () {
// This function closes the popup and sets the seat to not selected
$( '#overlay' ).hide( 200 );
let seat = JSON.parse( sessionStorage.getItem( 'tempStorage' ) );
this.seating[ seat[ 1 ][ 1 ] ][ 'content' ][ seat[ 1 ][ 0 ] ][ 'selected' ] = false;
},
storeSeat( ticketOption ) {
/*
This function stores a ticket into the event's selected seat sessionStorage.
*/
let cart = sessionStorage.getItem( 'cart' ) ? JSON.parse( sessionStorage.getItem( 'cart' ) ) : {};
cart[ this.ticketID ?? 'default' ] = cart[ this.ticketID ?? 'default' ] ? cart[ this.ticketID ?? 'default' ] : { 'name': this.eventInfo.name, 'date': this.eventInfo.date, 'location': this.eventInfo.location, 'currency': this.eventInfo.currency };
cart[ this.ticketID ?? 'default' ][ 'selectedSeats' ] = cart[ this.ticketID ?? 'default' ][ 'selectedSeats' ] ? cart[ this.ticketID ?? 'default' ][ 'selectedSeats' ] : {};
let data = cart[ this.ticketID ?? 'default' ][ 'selectedSeats' ] ? cart[ this.ticketID ?? 'default' ][ 'selectedSeats' ] : {};
let seat = JSON.parse( sessionStorage.getItem( 'tempStorage' ) );
let ticket = this.seating[ seat[ 1 ][ 1 ] ][ 'content' ][ seat[ 1 ][ 0 ] ];
let ticketData = { 'name': ticket[ 'name' ], 'categoryID': ticketOption, 'category': this.eventInfo[ 'categories' ][ ticket[ 'category' ] ], 'price': this.eventInfo[ 'categories' ][ this.seating[ seat[ 1 ][ 1 ] ][ 'content' ][ seat[ 1 ][ 0 ] ][ 'category' ] ][ 'price' ][ ticketOption ], 'row':seat[ 1 ][ 1 ], 'seat':seat[ 1 ][ 0 ], 'ageGroup': this.eventInfo[ 'ageGroups' ][ ticketOption ][ 'name' ] };
data[ String( seat[ 1 ][ 1 ] ) + String( seat[ 1 ][ 0 ] ) ] = ticketData;
cart[ this.ticketID ?? 'default' ][ 'selectedSeats' ] = data;
sessionStorage.setItem( 'cart', JSON.stringify( cart ) );
$( '#overlay' ).hide( 200 );
this.selectedSeats = cart;
this.sumUp();
},
},
created() {
this.loadPreviouslySelected();
}
}
</script>
<style scoped>
.seatingWrapper {
display: grid;
grid-template-areas:
'main main main sidebar'
'main main main sidebar'
'main main main sidebar'
'main main main sidebar'
'main main main sidebar'
'main main main sidebar'
'main main main sidebar'
'main main main sidebar'
'main main main sidebar';
height: 100%;
}
.sidebar {
grid-area: sidebar;
background-color: var( --accent-background );
color: var( --secondary-color );
overflow: scroll;
}
.seatingPlan {
grid-area: main;
display: flex;
flex-direction: column;
align-items: center;
justify-content: justify;
overflow: scroll;
}
.active {
cursor: pointer;
}
.occupied {
background-color: var( --hover-color );
padding: 0.4%;
}
.overlay {
display: none;
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: var( --overlay-color );
height: 100%;
width: 100%;
}
.popup {
height: 100%;
width: 100%;
display: flex;
justify-content: center;
flex-direction: column;
align-items: center;
}
.popup-content {
background-color: var( --background-color );
height: 60%;
width: 50%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: flex-start;
border-radius: 50px;
}
.popup-content-wrapper {
display: flex;
height: 90%;
width: 100%;
flex-direction: column;
align-items: center;
justify-content: center;
overflow: scroll;
}
.close-container {
width: 100%;
display: flex;
justify-content: flex-end;
}
.close-button {
cursor: pointer;
margin-right: 3vh;
margin-top: 3vh;
}
.option {
list-style: none;
padding: 7px 15px;
border-radius: 10px;
border-color: var( --primary-color );
border-style: solid;
border-width: 1px;
margin: 3px 0px;
cursor: pointer;
}
.stage {
border-color: var( --primary-color );
border-style: solid;
width: 80%;
height: 7%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.button {
background-color: var( --accent-background );
color: var( --secondary-color );
font-weight: bold;
font-size: 110%;
border-radius: 20px;
border-style: none;
padding: 10px 40px;
transition: 0.6s;
}
.button:hover {
background-color: var( --accent-background-hover );
transition: 0.3s;
cursor: pointer;
}
.price-table {
width: 100%;
}
</style>

View File

@@ -78,7 +78,7 @@
<script> <script>
export default { export default {
name: 'noseatplan', name: 'seatplan',
props: { props: {
ticketID: String ticketID: String
}, },

View File

@@ -0,0 +1,66 @@
export default {
path: '/admin',
name: 'admin',
component: () => import( '../views/admin/AdminView.vue' ),
meta: {
title: 'Admin - myevent',
adminAuthRequired: true,
},
children: [
{
path: '',
name: 'adminHome',
component: () => import( '../views/admin/HomeView.vue' ),
meta: {
title: 'Home :: Admin - myevent',
adminAuthRequired: true,
}
},
{
path: 'admin-accounts',
name: 'adminAccounts',
component: () => import( '../views/admin/AccountView.vue' ),
meta: {
title: 'Accounts :: Admin - myevent',
adminAuthRequired: true,
permissions: 'root'
}
},
{
path: 'pages',
name: 'adminPages',
component: () => import( '../views/admin/PagesView.vue' ),
meta: {
title: 'Pages :: Admin - myevent',
adminAuthRequired: true,
}
},
{
path: 'events',
name: 'adminEvents',
component: () => import( '../views/admin/EventsView.vue' ),
meta: {
title: 'Events :: Admin - myevent',
adminAuthRequired: true,
}
},
{
path: 'plugins',
name: 'adminPlugins',
component: () => import( '../views/admin/PluginsView.vue' ),
meta: {
title: 'Plugins :: Admin - myevent',
adminAuthRequired: true,
}
},
{
path: 'settings',
name: 'adminSettings',
component: () => import( '../views/admin/SettingsView.vue' ),
meta: {
title: 'Admin - myevent',
adminAuthRequired: true,
}
},
]
}

View File

@@ -1,206 +1,17 @@
import { createRouter, createWebHistory } from 'vue-router' import { createRouter, createWebHistory } from 'vue-router'
import HomeView from '../views/HomeView.vue'
import { useUserStore } from '@/stores/userStore'; import { useUserStore } from '@/stores/userStore';
import { useBackendStore } from '@/stores/backendStore';
import adminRoutes from '@/router/adminRoutes';
import mainRoutes from '@/router/mainRoutes';
/* /*
This is the Vue.js router file. Here, all valid routes are defined. This is the Vue.js router file. All valid routes get imported from other files to
improve code legibility. Only router logic and importing logic is defined here.
*/ */
const routes = [
{ const routes = mainRoutes;
path: '/',
name: 'home', routes.push( adminRoutes );
component: HomeView,
meta: {
title: 'Home - myevent'
}
},
{
path: '/tickets',
name: 'tickets',
component: () => import( '../views/OrderView.vue' ),
meta: {
title: 'Order ticket - myevent'
}
},
{
path: '/login',
name: 'login',
component: () => import( '../views/LoginView.vue' ),
meta: {
title: 'Login - myevent'
}
},
{
path: '/admin/login',
name: 'adminLogin',
component: () => import( '../views/AdminLoginView.vue' ),
meta: {
title: 'Login :: Admin - myevent'
}
},
{
path: '/setup',
name: 'setup',
component: () => import( '../views/SetupView.vue' ),
meta: {
title: 'Login :: Admin - myevent',
requiresSetupKey: true,
},
children: [
{
path: '',
name: 'setupStart',
component: () => import( '../views/setup/SetupStartView.vue' ),
meta: {
title: 'Start :: Setup - myevent',
adminAuthRequired: true,
}
},
{
path: 'root',
name: 'setupRoot',
component: () => import( '../views/setup/SetupRootView.vue' ),
meta: {
title: 'Root account :: Setup - myevent',
adminAuthRequired: true,
}
},
{
path: 'page',
name: 'setupPage',
component: () => import( '../views/setup/SetupPageView.vue' ),
meta: {
title: 'Landing page :: Setup - myevent',
adminAuthRequired: true,
}
},
]
},
{
path: '/admin',
name: 'admin',
component: () => import( '../views/admin/AdminView.vue' ),
meta: {
title: 'Admin - myevent',
adminAuthRequired: true,
},
children: [
{
path: '',
name: 'adminMain',
component: () => import( '../views/admin/HomeView.vue' ),
meta: {
title: 'Home :: Admin - myevent',
adminAuthRequired: true,
}
},
{
path: 'admin-accounts',
name: 'adminAccounts',
component: () => import( '../views/admin/AccountView.vue' ),
meta: {
title: 'Accounts :: Admin - myevent',
adminAuthRequired: true,
permissions: 'root'
}
},
{
path: 'pages',
name: 'adminPages',
component: () => import( '../views/admin/PagesView.vue' ),
meta: {
title: 'Pages :: Admin - myevent',
adminAuthRequired: true,
}
},
{
path: 'events',
name: 'adminEvents',
component: () => import( '../views/admin/EventsView.vue' ),
meta: {
title: 'Events :: Admin - myevent',
adminAuthRequired: true,
}
},
{
path: 'plugins',
name: 'adminPlugins',
component: () => import( '../views/admin/PluginsView.vue' ),
meta: {
title: 'Plugins :: Admin - myevent',
adminAuthRequired: true,
}
},
{
path: 'settings',
name: 'adminSettings',
component: () => import( '../views/admin/SettingsView.vue' ),
meta: {
title: 'Admin - myevent',
adminAuthRequired: true,
}
},
]
},
{
path: '/signup',
name: 'signup',
component: () => import( '../views/SignupView.vue' ),
meta: {
title: 'Signup - myevent'
}
},
{
path: '/tickets/details',
name: 'ticketDetails',
component: () => import( '../views/TicketsDetailsView.vue' ),
meta: {
title: 'Details - myevent',
transition: 'scale'
}
},
{
path: '/tickets/order',
name: 'ticketOrder',
component: () => import( '../views/TicketsOrderingView.vue' ),
meta: {
title: 'Order ticket - myevent',
transition: 'scale'
}
},
{
path: '/cart',
name: 'cart',
component: () => import( '../views/CartView.vue' ),
meta: {
title: 'Cart - myevent',
transition: 'scale'
}
},
{
path: '/purchase',
name: 'purchase',
component: () => import( '@/views/PurchaseView.vue' ),
meta: {
title: 'Pay - myevent',
transition: 'scale'
}
},
{
path: '/pay',
name: 'pay',
component: () => import( '@/views/PaymentView.vue' ),
meta: {
title: 'Pay - myevent',
transition: 'scale',
}
},
{
path: '/:pathMatch(.*)*',
name: 'NotFound',
component: () => import( '@/views/404.vue')
},
]
const router = createRouter( { const router = createRouter( {
history: createWebHistory( process.env.BASE_URL ), history: createWebHistory( process.env.BASE_URL ),
@@ -212,11 +23,14 @@ router.afterEach( ( to, from ) => {
document.title = to.meta.title ? to.meta.title : 'myevent'; document.title = to.meta.title ? to.meta.title : 'myevent';
} ); } );
/* let doSetup = true;
TODO: Get auth status from server on reload
*/
let AdminPages = [ 'admin', 'adminMain' ]; if ( doSetup ) {
import( '@/router/setupRoutes' ).then( data => {
router.addRoute( data.default );
router.replace( window.location.pathname );
} );
}
let UserAccountPages = [ 'account' ]; let UserAccountPages = [ 'account' ];
@@ -224,19 +38,23 @@ let authRequired = false;
router.beforeEach( ( to, from ) => { router.beforeEach( ( to, from ) => {
let userStore = useUserStore(); let userStore = useUserStore();
let backendStore = useBackendStore();
backendStore.loadVisitedSetupPages();
let isUserAuthenticated = userStore.getUserAuthenticated; let isUserAuthenticated = userStore.getUserAuthenticated;
let isAdminAuthenticated = userStore.getAdminAuthenticated; let isAdminAuthenticated = userStore.getAdminAuthenticated;
if ( to.meta.adminAuthRequired && !isAdminAuthenticated ) { if ( to.meta.adminAuthRequired && !isAdminAuthenticated ) {
return { name: 'adminLogin' }; return { name: 'adminLogin' };
} else if ( to.name === 'adminLogin' && isAdminAuthenticated ) { } else if ( to.name === 'adminLogin' && isAdminAuthenticated ) {
return { name: 'admin' }; return { name: 'adminHome' };
} else if ( UserAccountPages.includes( to.name ) && !isUserAuthenticated ) { } else if ( UserAccountPages.includes( to.name ) && !isUserAuthenticated ) {
return { name: 'login' }; return { name: 'login' };
} else if ( !isUserAuthenticated && to.name === 'purchase' && authRequired ) { } else if ( !isUserAuthenticated && to.name === 'purchase' && authRequired ) {
return { name: 'login' }; return { name: 'login' };
} else if ( !isUserAuthenticated && to.name === 'pay' ) { } else if ( !isUserAuthenticated && to.name === 'pay' ) {
return { name: 'purchase' }; return { name: 'purchase' };
} else if ( to.name.substring( 0, 5 ) === 'setup' && !backendStore.getVisitedSetupPages[ to.name.substring( 5 ).toLowerCase() ] && to.name.substring( 5 ).toLowerCase() !== 'start' ) {
return { name: 'setupStart' };
} }
} ); } );

View File

@@ -0,0 +1,94 @@
import HomeView from '../views/HomeView.vue';
export default [
{
path: '/',
name: 'home',
component: HomeView,
meta: {
title: 'Home - myevent'
}
},
{
path: '/tickets',
name: 'tickets',
component: () => import( '../views/OrderView.vue' ),
meta: {
title: 'Order ticket - myevent'
}
},
{
path: '/login',
name: 'login',
component: () => import( '../views/LoginView.vue' ),
meta: {
title: 'Login - myevent'
}
},
{
path: '/admin/login',
name: 'adminLogin',
component: () => import( '../views/AdminLoginView.vue' ),
meta: {
title: 'Login :: Admin - myevent'
}
},
{
path: '/signup',
name: 'signup',
component: () => import( '../views/SignupView.vue' ),
meta: {
title: 'Signup - myevent'
}
},
{
path: '/tickets/details',
name: 'ticketDetails',
component: () => import( '../views/TicketsDetailsView.vue' ),
meta: {
title: 'Details - myevent',
transition: 'scale'
}
},
{
path: '/tickets/order',
name: 'ticketOrder',
component: () => import( '../views/TicketsOrderingView.vue' ),
meta: {
title: 'Order ticket - myevent',
transition: 'scale'
}
},
{
path: '/cart',
name: 'cart',
component: () => import( '../views/CartView.vue' ),
meta: {
title: 'Cart - myevent',
transition: 'scale'
}
},
{
path: '/purchase',
name: 'purchase',
component: () => import( '@/views/PurchaseView.vue' ),
meta: {
title: 'Pay - myevent',
transition: 'scale'
}
},
{
path: '/pay',
name: 'pay',
component: () => import( '@/views/PaymentView.vue' ),
meta: {
title: 'Pay - myevent',
transition: 'scale',
}
},
{
path: '/:pathMatch(.*)*',
name: 'NotFound',
component: () => import( '@/views/404.vue')
},
]

View File

@@ -0,0 +1,74 @@
export default {
path: '/setup',
name: 'setup',
component: () => import( '../views/SetupView.vue' ),
meta: {
title: 'Login :: Admin - myevent',
adminAuthRequired: true,
},
children: [
{
path: '',
name: 'setupStart',
component: () => import( '../views/setup/SetupStartView.vue' ),
meta: {
title: 'Start :: Setup - myevent',
adminAuthRequired: true,
}
},
{
path: 'root',
name: 'setupRoot',
component: () => import( '../views/setup/SetupRootView.vue' ),
meta: {
title: 'Root account :: Setup - myevent',
adminAuthRequired: true,
}
},
{
path: 'page',
name: 'setupPage',
component: () => import( '../views/setup/SetupPageView.vue' ),
meta: {
title: 'Landing page :: Setup - myevent',
adminAuthRequired: true,
}
},
{
path: 'payments',
name: 'setupPayments',
component: () => import( '../views/setup/SetupPaymentsView.vue' ),
meta: {
title: 'Payments :: Setup - myevent',
adminAuthRequired: true,
}
},
{
path: 'events',
name: 'setupEvents',
component: () => import( '../views/setup/SetupEventsView.vue' ),
meta: {
title: 'Events :: Setup - myevent',
adminAuthRequired: true,
}
},
{
path: 'tos',
name: 'setupTOS',
component: () => import( '../views/setup/SetupTOSView.vue' ),
meta: {
title: 'TOS (Optional) :: Setup - myevent',
adminAuthRequired: true,
}
},
{
path: 'complete',
name: 'setupComplete',
component: () => import( '../views/setup/SetupCompleteView.vue' ),
meta: {
title: 'Setup complete :: Setup - myevent',
adminAuthRequired: true,
}
},
]
}

View File

@@ -0,0 +1,17 @@
import { defineStore } from "pinia";
export const useBackendStore = defineStore ( 'backend', {
state: () => ( { 'visitedSetupPages': {} } ),
getters: {
getVisitedSetupPages: ( state ) => state.visitedSetupPages,
},
actions: {
addVisitedSetupPages ( page, data ) {
this.visitedSetupPages[ page ] = data;
sessionStorage.setItem( 'visitedSetupPages', JSON.stringify( this.visitedSetupPages ) );
},
loadVisitedSetupPages () {
this.visitedSetupPages = sessionStorage.getItem( 'visitedSetupPages' ) ? JSON.parse( sessionStorage.getItem( 'visitedSetupPages' ) ) : {};
}
}
} );

View File

@@ -3,14 +3,15 @@
<h1>Purchase</h1> <h1>Purchase</h1>
<h3>Personal information</h3> <h3>Personal information</h3>
<div class="purchase-app"> <div class="purchase-app">
<form>
<div v-if="!isAuthenticated"> <div v-if="!isAuthenticated">
<form>
<label for="email">Email address *</label><br> <label for="email">Email address *</label><br>
<input type="email" name="email" id="email" required v-model="formData.email"> <input type="email" name="email" id="email" required v-model="formData.email">
</div>
</form> </form>
<router-link to="/login">Log in with an existing account</router-link>
</div>
<div v-else></div>
</div> </div>
</div> </div>
</template> </template>

View File

@@ -1,6 +1,21 @@
<template> <template>
<div> <div>
<h1>Setup</h1> <h1>Setup</h1>
<nav>
<router-link to="/setup">Start</router-link> |
<router-link to="/setup/root" v-if="backendStore.getVisitedSetupPages[ 'root' ]">Root account</router-link>
<a v-else class="inactive">Root account</a> |
<router-link to="/setup/page" v-if="backendStore.getVisitedSetupPages[ 'page' ]">Landing page</router-link>
<a v-else class="inactive">Landing page</a> |
<router-link to="/setup/payments" v-if="backendStore.getVisitedSetupPages[ 'payments' ]">Payments</router-link>
<a v-else class="inactive">Payments</a> |
<router-link to="/setup/events" v-if="backendStore.getVisitedSetupPages[ 'events' ]">Events</router-link>
<a v-else class="inactive">Events</a> |
<router-link to="/setup/tos" v-if="backendStore.getVisitedSetupPages[ 'tos' ]">TOS</router-link>
<a v-else class="inactive">TOS</a> |
<router-link to="/setup/complete" v-if="backendStore.getVisitedSetupPages[ 'complete' ]">Complete</router-link>
<a v-else class="inactive">Complete</a>
</nav>
<div class="main-view"> <div class="main-view">
<router-view v-slot="{ Component, route }"> <router-view v-slot="{ Component, route }">
<transition :name="route.meta.transition || 'scale'" mode="out-in"> <transition :name="route.meta.transition || 'scale'" mode="out-in">
@@ -12,16 +27,28 @@
</template> </template>
<script> <script>
import { useBackendStore } from '@/stores/backendStore';
import { mapStores } from 'pinia';
export default { export default {
data () { data () {
return { return {
formData: {} formData: {}
} }
}, },
methods: { computed: {
setup () { ...mapStores( useBackendStore )
},
} created () {
this.backendStore.loadVisitedSetupPages();
}, },
}; };
</script> </script>
<style scoped>
.inactive {
color: var( --inactive-color );
cursor: not-allowed;
}
</style>

View File

@@ -1,7 +1,8 @@
<template> <template>
<div class="details"> <div class="details">
<!-- Load correct component depending on what the event's config is --> <!-- Load correct component depending on what the event's config is -->
<seatplan ticketID="haoag"></seatplan> <seatplan ticketID="haoag" v-if="hasSeatplan"></seatplan>
<noseatplan ticketID="haoag" v-else></noseatplan>
</div> </div>
</template> </template>
@@ -13,11 +14,18 @@
<script> <script>
import seatplan from '@/components/seatplan.vue'; import seatplan from '@/components/seatplan.vue';
import noseatplan from '@/components/noseatplan.vue';
export default { export default {
name: 'TicketsDetailsView', name: 'TicketsDetailsView',
components: { components: {
seatplan seatplan,
noseatplan
},
data() {
return {
hasSeatplan: true,
}
}, },
created () { created () {
if ( !sessionStorage.getItem( 'selectedTicket' ) ) { if ( !sessionStorage.getItem( 'selectedTicket' ) ) {

View File

@@ -0,0 +1,6 @@
<template>
<div>
<h2>Setup was completed!</h2>
<router-link to="/admin">To the admin panel</router-link>
</div>
</template>

View File

@@ -0,0 +1,30 @@
<template>
<div>
<h3>Setting up Events</h3>
<p>You may choose all of the below payment methods, but we recommend to only select one payment gateway for simplicity. Recommended: Either Stripe or Adyen. See the comparison of the different payment methods <a href="https://myevent.janishutz.com/docs/payments">here</a></p>
<p>You may find more infos about this part <a href="https://myevent.janishutz.com/docs/setup/setup#payment-methods" target="_blank">here</a></p>
<button @click="submit()">Continue</button>
</div>
</template>
<script>
import { useBackendStore } from '@/stores/backendStore';
import { mapStores } from 'pinia';
export default {
data () {
return {
formData: {}
}
},
computed: {
...mapStores( useBackendStore )
},
methods: {
submit () {
this.backendStore.addVisitedSetupPages( 'tos', true );
this.$router.push( '/setup/tos' );
}
},
};
</script>

View File

@@ -1,21 +1,35 @@
<template> <template>
<div> <div>
<h3>Setting up the landing page</h3> <h3>Setting up the landing page</h3>
<p>The landing page is the page your customers see when they visit your webpage. You may select a page template <a href="https://myevent.janishutz.com/docs/homepage/templates"></a></p> <p>The landing page is the page your customers see when they visit your webpage. You may select a page template <a href="https://myevent.janishutz.com/docs/homepage/templates">here</a>.</p>
<p>You may find more infos about this part <a href="https://myevent.janishutz.com/docs/setup/setup#page-setup" target="_blank">here</a></p> <p>You may find more infos about this part <a href="https://myevent.janishutz.com/docs/setup/setup#page-setup" target="_blank">here</a></p>
<label for="template">Choose a template</label><br>
<select name="template" id="template" v-for="option in options">
<option :value="option.id">{{ option.name }}</option>
</select><br>
<button @click="submit()">Continue</button>
</div> </div>
</template> </template>
<script> <script>
import { useBackendStore } from '@/stores/backendStore';
import { mapStores } from 'pinia';
export default { export default {
data () { data () {
return { return {
formData: {} options: { 'default': { 'id': 'default', 'name': 'Default' }},
} }
}, },
computed: {
...mapStores( useBackendStore )
},
methods: { methods: {
submit () { submit () {
this.backendStore.addVisitedSetupPages( 'payments', true );
this.$router.push( '/setup/payments' );
} }
}, },
}; };

View File

@@ -1,37 +1,29 @@
<template> <template>
<div> <div>
<h3>Setting up payment methods</h3> <h3>Setting up payment methods</h3>
<p>The root account is the most powerful account. Therefore, it should only be used if really necessary and should have a strong password. It also always requires Two Factor Authentication for added security. You may log into the root account by typing 'root' into the Email/Username field on the admin login screen.</p> <p>You may choose all of the below payment methods, but we recommend to only select one payment gateway for simplicity. Recommended: Either Stripe or Adyen. See the comparison of the different payment methods <a href="https://myevent.janishutz.com/docs/payments">here</a></p>
<p>You may find more infos about this part <a href="https://myevent.janishutz.com/docs/setup/setup#root-account" target="_blank">here</a></p> <p>You may find more infos about this part <a href="https://myevent.janishutz.com/docs/setup/setup#payment-methods" target="_blank">here</a></p>
<p>Password requirements:</p>
<ul style="list-style: none;">
<li>At least 15 characters long</li>
<li>At least 2 special characters</li>
<li>At least 2 numbers</li>
<li>At least 2 lower and 2 upper case letters</li>
</ul>
<form>
<label for="mail">Email address for 2FA</label><br>
<input type="email" name="mail" id="mail"><br>
<label for="password">Password</label><br>
<input type="email" name="password" id="password"><br>
<label for="password2">Confirm password</label><br>
<input type="email" name="password2" id="password2">
</form>
<button @click="submit()">Continue</button> <button @click="submit()">Continue</button>
</div> </div>
</template> </template>
<script> <script>
import { useBackendStore } from '@/stores/backendStore';
import { mapStores } from 'pinia';
export default { export default {
data () { data () {
return { return {
formData: {} formData: {}
} }
}, },
computed: {
...mapStores( useBackendStore )
},
methods: { methods: {
submit () { submit () {
this.backendStore.addVisitedSetupPages( 'events', true );
this.$router.push( '/setup/events' );
} }
}, },
}; };

View File

@@ -23,14 +23,21 @@
</template> </template>
<script> <script>
import { useBackendStore } from '@/stores/backendStore';
import { mapStores } from 'pinia';
export default { export default {
data () { data () {
return { return {
formData: {} formData: {}
} }
}, },
computed: {
...mapStores( useBackendStore )
},
methods: { methods: {
submit () { submit () {
this.backendStore.addVisitedSetupPages( 'page', true );
this.$router.push( 'page' ); this.$router.push( 'page' );
} }
}, },

View File

@@ -1,21 +1,28 @@
<template> <template>
<div> <div>
<h3>Welcome to myevent!</h3> <h2>Welcome to myevent!</h2>
<i style="font-size: small;">All links during setup open in separate tabs</i>
<p>Let's start by setting it up. We strongly encourage you to also have a look at the extensive documentation of the setup process <a href="https://myevent.janishutz.com/docs/setup/setup" target="_blank">here</a></p> <p>Let's start by setting it up. We strongly encourage you to also have a look at the extensive documentation of the setup process <a href="https://myevent.janishutz.com/docs/setup/setup" target="_blank">here</a></p>
<router-link to="/setup/root">Start setup</router-link> <router-link to="/setup/root" @click="setup();">Start setup</router-link>
</div> </div>
</template> </template>
<script> <script>
import { useBackendStore } from '@/stores/backendStore';
import { mapStores } from 'pinia';
export default { export default {
data () { data () {
return { return {
formData: {} formData: {}
} }
}, },
computed: {
...mapStores( useBackendStore )
},
methods: { methods: {
setup () { setup () {
this.backendStore.addVisitedSetupPages( 'root', true );
} }
}, },
}; };

View File

@@ -0,0 +1,30 @@
<template>
<div>
<h3>Setting up TOS (optional)</h3>
<p>You may choose all of the below payment methods, but we recommend to only select one payment gateway for simplicity. Recommended: Either Stripe or Adyen. See the comparison of the different payment methods <a href="https://myevent.janishutz.com/docs/payments" target="_blank">here</a></p>
<p>You may find more infos about this part <a href="https://myevent.janishutz.com/docs/setup/setup#payment-methods" target="_blank">here</a></p>
<button @click="submit()">Continue</button>
</div>
</template>
<script>
import { useBackendStore } from '@/stores/backendStore';
import { mapStores } from 'pinia';
export default {
data () {
return {
formData: {}
}
},
computed: {
...mapStores( useBackendStore )
},
methods: {
submit () {
this.backendStore.addVisitedSetupPages( 'complete', true );
this.$router.push( '/setup/complete' );
}
},
};
</script>