@@ -1,7 +1,6 @@
|
||||
import axios from 'axios'
|
||||
|
||||
export default axios.create({
|
||||
baseURL: 'https://localhost:8080/',
|
||||
timeout: 1000,
|
||||
headers: { 'X-Custom-Header': 'foobar' }
|
||||
baseURL: 'https://88c09a70-ab85-412a-9bd3-407afe8986a1.mock.pstmn.io/',
|
||||
timeout: 4000
|
||||
})
|
||||
|
||||
@@ -5,12 +5,13 @@ import { createI18n } from './i18n'
|
||||
import store from './store'
|
||||
import { library } from '@fortawesome/fontawesome-svg-core'
|
||||
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome'
|
||||
import { faUserSecret } from '@fortawesome/free-solid-svg-icons'
|
||||
import { faUserSecret, faPenToSquare } from '@fortawesome/free-solid-svg-icons'
|
||||
|
||||
import './assets/main.css'
|
||||
|
||||
/* add icons to the library */
|
||||
library.add(faUserSecret)
|
||||
library.add(faPenToSquare)
|
||||
|
||||
const i18n = createI18n()
|
||||
|
||||
|
||||
@@ -77,6 +77,14 @@ const router = createRouter({
|
||||
requiresAuth: false
|
||||
}
|
||||
},
|
||||
{
|
||||
path: '/error',
|
||||
name: 'error',
|
||||
component: () => import('../views/ErrorView.vue'),
|
||||
meta: {
|
||||
requiresAuth: false
|
||||
}
|
||||
},
|
||||
{
|
||||
path: '/:pathMatch(.*)*',
|
||||
name: 'notfound',
|
||||
|
||||
12
src/service/getContracts.js
Normal file
12
src/service/getContracts.js
Normal file
@@ -0,0 +1,12 @@
|
||||
import HttpClient from '../api/HttpClient'
|
||||
import router from '../router'
|
||||
|
||||
export async function getContracts() {
|
||||
return HttpClient.get('contracts')
|
||||
.then(resp => {
|
||||
return resp.data.contracts
|
||||
})
|
||||
.catch(error => {
|
||||
router.push('/error?message=' + error.message + '&code=' + error.code)
|
||||
})
|
||||
}
|
||||
21
src/store/contracts.module.js
Normal file
21
src/store/contracts.module.js
Normal file
@@ -0,0 +1,21 @@
|
||||
import { getContracts } from '../service/getContracts'
|
||||
import HttpClient from '../api/HttpClient'
|
||||
import router from '../router'
|
||||
|
||||
export default {
|
||||
state: () => ({
|
||||
contracts: []
|
||||
}),
|
||||
mutations: {
|
||||
initContracts(state, data) {
|
||||
state.contracts = data
|
||||
}
|
||||
},
|
||||
actions: {
|
||||
async fetchContracts({ commit }) {
|
||||
const contracts = await getContracts()
|
||||
commit('initContracts', contracts)
|
||||
}
|
||||
},
|
||||
getters: {}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
import { createStore } from 'vuex'
|
||||
import moduleA from './moduleA.module'
|
||||
import contracts from './contracts.module'
|
||||
import moduleB from './moduleB.module'
|
||||
import keycloak from './keycloak.module'
|
||||
import createPersistedState from 'vuex-persistedstate'
|
||||
@@ -7,7 +7,7 @@ import createPersistedState from 'vuex-persistedstate'
|
||||
export default createStore({
|
||||
modules: {
|
||||
keycloak: keycloak,
|
||||
a: moduleA,
|
||||
contracts: contracts,
|
||||
b: moduleB
|
||||
},
|
||||
plugins: [createPersistedState()]
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
export default {
|
||||
state: () => ({}),
|
||||
mutations: {},
|
||||
actions: {},
|
||||
getters: {}
|
||||
}
|
||||
@@ -1,15 +1,97 @@
|
||||
<script setup>
|
||||
import Navbar from '../components/Navbar.vue'
|
||||
</script>
|
||||
<script>
|
||||
export default {
|
||||
mounted() {}
|
||||
}
|
||||
import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome";
|
||||
</script>
|
||||
<template>
|
||||
<Navbar /><!-- Causes rerendering each time todo: possible use in App.vue-->
|
||||
<div class="about">
|
||||
<h1>This is an Contracts page</h1>
|
||||
<div class="flex justify-center pt-8 pb-8">
|
||||
<p
|
||||
class="text-2xl md:text-2xl lg:text-3xl xl:text-4xl 2xl:text-5xl font-serif font-medium tracking-wide flex justify-center items-center">
|
||||
<span class="inline-block w-5 h-1 mr-4 bg-gray-900 ::before"></span>
|
||||
Aufträge
|
||||
<span class="inline-block w-5 h-1 ml-4 bg-gray-900 ::after"></span>
|
||||
</p>
|
||||
</div>
|
||||
<div class="flex justify-center pb-6">
|
||||
<div class="overflow-x-auto">
|
||||
<RouterLink v-if="isVerwaltung" to="/contract/create">
|
||||
<button class="bg-sky-500 text-white active:bg-sky-600 font-bold uppercase text-xs px-4 py-2 mb-3 rounded shadow hover:shadow-md outline-none focus:outline-none mr-1 mb-1 ease-linear transition-all duration-150" type="button"
|
||||
>
|
||||
Create Auftrag
|
||||
</button>
|
||||
</RouterLink>
|
||||
<RouterLink v-if="isEmployee" to="/contracts/register">
|
||||
<button class="bg-emerald-500 text-white active:bg-emerald-600 font-bold uppercase text-xs px-4 py-2 rounded shadow hover:shadow-md outline-none focus:outline-none mr-1 mb-1 ease-linear transition-all duration-150" type="button"
|
||||
>
|
||||
<font-awesome-icon icon="fa-solid fa-pen-to-square" class="pr-1 h-3.5"/> Für Auftrag anmelden
|
||||
</button>
|
||||
</RouterLink>
|
||||
<table class="min-w-full border-collapse bg-white border border-gray-600">
|
||||
<thead class="bg-gray-800 text-white">
|
||||
<tr>
|
||||
<th class="text-left py-3 px-4 uppercase font-semibold text-sm text-center">Id</th>
|
||||
<th class="text-left py-3 px-4 uppercase font-semibold text-sm text-center">Name</th>
|
||||
<th class="text-left py-3 px-4 uppercase font-semibold text-sm text-center">Status</th>
|
||||
<th class="w-1/3 text-left py-3 px-4 uppercase font-semibold text-sm text-center">Mitarbeiter</th>
|
||||
<th class="text-left py-3 px-4 uppercase font-semibold text-sm text-center">Updated</th>
|
||||
<th class="text-left py-3 px-4 uppercase font-semibold text-sm text-center">Aktion</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="text-gray-700">
|
||||
<tr v-for="(contract, index) in contracts" :key="contract.id" :class="{ 'bg-gray-100': index % 2 !== 0 }">
|
||||
<td class="text-left py-3 px-4 text-center">{{ contract.id }}</td>
|
||||
<td class="text-left py-3 px-4 text-center">{{ contract.name }}</td>
|
||||
<td class="text-left py-3 px-4 text-center">
|
||||
<!-- todo: set color specific from status. for colors use https://www.creative-tim.com/learning-lab/tailwind-starter-kit/documentation/css/labels -->
|
||||
<span class="text-emerald-600 bg-emerald-200 rounded-full py-1 px-2">{{ contract.status }}</span>
|
||||
</td>
|
||||
<td class="text-left py-3 px-4 text-center">{{ contract.mitarbeiter.join(', ') }}</td>
|
||||
<td class="text-left py-3 px-4 text-center">{{ new Date(contract.updatedAt).toDateString() }}</td>
|
||||
<td class="text-left py-2">
|
||||
<button @click="openDeleteDialog()" class="bg-red-500 text-white active:bg-red-600 font-bold uppercase text-xs px-4 py-2 rounded shadow hover:shadow-md outline-none focus:outline-none mr-1 mb-1 ease-linear transition-all duration-150" type="button"
|
||||
>
|
||||
Delete
|
||||
</button>
|
||||
<button class="bg-amber-500 text-white active:bg-amber-600 font-bold uppercase text-xs px-4 py-2 rounded shadow hover:shadow-md outline-none focus:outline-none mr-1 mb-1 ease-linear transition-all duration-150" type="button"
|
||||
>
|
||||
Update
|
||||
</button>
|
||||
<button class="bg-emerald-500 text-white active:bg-emerald-600 font-bold uppercase text-xs px-4 py-2 rounded shadow hover:shadow-md outline-none focus:outline-none mr-1 mb-1 ease-linear transition-all duration-150" type="button"
|
||||
>
|
||||
View
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<style></style>
|
||||
<script>
|
||||
import { mapActions } from "vuex";
|
||||
|
||||
export default {
|
||||
mounted() {
|
||||
this.fetchContracts()
|
||||
},
|
||||
methods: {
|
||||
...mapActions([
|
||||
'fetchContracts'
|
||||
]),
|
||||
openDeleteDialog() {
|
||||
console.log("Prepare to delete")
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
contracts() {
|
||||
return this.$store.state.contracts.contracts
|
||||
},
|
||||
isVerwaltung() {
|
||||
return this.$store.state.keycloak.keycloak.realmAccess.roles.includes('verwaltung')
|
||||
},
|
||||
isEmployee(){
|
||||
return this.$store.state.keycloak.keycloak.realmAccess.roles.includes('employee')
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
48
src/views/ErrorView.vue
Normal file
48
src/views/ErrorView.vue
Normal file
@@ -0,0 +1,48 @@
|
||||
<script setup>
|
||||
import Navbar from '../components/Navbar.vue'
|
||||
</script>
|
||||
<template>
|
||||
<Navbar/>
|
||||
<div
|
||||
class="
|
||||
flex
|
||||
items-center
|
||||
justify-center
|
||||
bg-gradient-to-r
|
||||
from-indigo-600
|
||||
to-blue-400
|
||||
py-10
|
||||
"
|
||||
>
|
||||
<div class="md:px-40 md:py-20 bg-white rounded-md shadow-xl">
|
||||
<div class="flex flex-col items-center">
|
||||
<h1 class="font-bold text-blue-600 text-3xl">{{code}}</h1>
|
||||
|
||||
<h6 class="mb-2 text-2xl font-bold text-center text-gray-800 md:text-3xl">
|
||||
<span class="text-red-500">Oops!</span> Error happend
|
||||
</h6>
|
||||
|
||||
<p class="mb-8 text-center text-gray-500 md:text-lg">
|
||||
{{ message }}
|
||||
</p>
|
||||
|
||||
<div class="pb-10">
|
||||
<RouterLink to="/" class="px-6 py-2 text-sm font-semibold text-blue-800 bg-blue-100">
|
||||
Go home
|
||||
</RouterLink>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
data(){
|
||||
return {
|
||||
message: this.$route.query.message,
|
||||
code: this.$route.query.code
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
Reference in New Issue
Block a user