* almost ready to release

This commit is contained in:
2023-01-16 22:38:22 +01:00
parent 7d03a8563a
commit 95d8d45919
6 changed files with 265 additions and 17 deletions

View File

@@ -19,7 +19,13 @@ import DeregisterModal from './components/modals/DeregisterModal.vue'
import RegisterModal from './components/modals/RegisterModal.vue' import RegisterModal from './components/modals/RegisterModal.vue'
export default { export default {
components: { DeregisterModal, RegisterModal, CreateModal, DeleteModal, ChangeStatusModal }, components: {
DeregisterModal,
RegisterModal,
CreateModal,
DeleteModal,
ChangeStatusModal
},
computed: { computed: {
modal() { modal() {
return this.$store.state.modal.modal return this.$store.state.modal.modal

View File

@@ -132,7 +132,7 @@ export default {
}) })
.catch(error => { .catch(error => {
console.error(error) console.error(error)
router.push('/error?message=' + error.message + '&code=' + error.code) this.$router.push('/error?message=' + error.message + '&code=' + error.code)
}) })
this.closeModal() this.closeModal()
} }

View File

@@ -86,7 +86,7 @@
<td class="text align-top text-xl pl-4 max-sm:text-base py-2">Unterlagen:</td> <td class="text align-top text-xl pl-4 max-sm:text-base py-2">Unterlagen:</td>
<td class="w-full pl-2 text-lg max-sm:text-base py-2"> <td class="w-full pl-2 text-lg max-sm:text-base py-2">
<ul class="list-disc pl-4"> <ul class="list-disc pl-4">
<li v-for="document in contract.unterlagen" :key="document.id"> <li v-for="document in contract.files" :key="document.name">
<a :href="document.url" class="underline"> <a :href="document.url" class="underline">
{{ document.name }} {{ document.name }}
<font-awesome-icon <font-awesome-icon
@@ -99,7 +99,7 @@
</tr> </tr>
<tr class="border-b"> <tr class="border-b">
<td class="text align-top text-xl pl-4 max-sm:text-base py-2">Beschreibung:</td> <td class="text align-top text-xl pl-4 max-sm:text-base py-2">Beschreibung:</td>
<td class="w-full pl-2 text-lg max-sm:text-base py-2">{{ contract.beschreibung }}</td> <td class="w-full pl-2 text-lg max-sm:text-base py-2">{{ contract.description }}</td>
</tr> </tr>
<tr> <tr>
<td class="text align-top text-xl pl-4 max-sm:text-base py-2">Beispiele:</td> <td class="text align-top text-xl pl-4 max-sm:text-base py-2">Beispiele:</td>

View File

@@ -14,7 +14,9 @@ import {
faCircleUser, faCircleUser,
faUserLarge, faUserLarge,
faCircleQuestion, faCircleQuestion,
faChalkboardUser faChalkboardUser,
faPlus,
faTrash
} from '@fortawesome/free-solid-svg-icons' } from '@fortawesome/free-solid-svg-icons'
import './assets/main.css' import './assets/main.css'
@@ -28,6 +30,8 @@ library.add(faCircleUser)
library.add(faUserLarge) library.add(faUserLarge)
library.add(faCircleQuestion) library.add(faCircleQuestion)
library.add(faChalkboardUser) library.add(faChalkboardUser)
library.add(faTrash)
library.add(faPlus)
const i18n = createI18n() const i18n = createI18n()

View File

@@ -87,14 +87,18 @@ export async function applyContract(contractID, prefRole, userName, userPhone, u
} }
export async function misapply(contractID) { export async function misapply(contractID) {
return HttpClient.post('/contract/' + contractID + '/misapply', { return HttpClient.post(
id : contractID, '/contract/' + contractID + '/misapply',
email : store.state.keycloak.keycloak.tokenParsed.email {
}, { id: contractID,
headers: { email: store.state.keycloak.keycloak.tokenParsed.email
Authorization: 'Bearer ' + store.state.keycloak.keycloak.token },
{
headers: {
Authorization: 'Bearer ' + store.state.keycloak.keycloak.token
}
} }
}) )
.then(resp => { .then(resp => {
//TODO: send also auth token with request //TODO: send also auth token with request
return resp.data return resp.data
@@ -205,3 +209,25 @@ export async function getAmountOfStatuses(token) {
router.push('/error?message=' + error.message + '&code=' + error.code) router.push('/error?message=' + error.message + '&code=' + error.code)
}) })
} }
export async function setupContract(conractId, data) {
return HttpClient.put(
'/contract/' + conractId + '/setup',
{
data
},
{
headers: {
Authorization: 'Bearer ' + store.state.keycloak.keycloak.token
}
}
)
.then(resp => {
//TODO: send also auth token with request
return resp.data
})
.catch(error => {
console.error(error)
router.push('/error?message=' + error.message + '&code=' + error.code)
})
}

View File

@@ -46,13 +46,149 @@
</li> </li>
</ul> </ul>
</div> </div>
<div class="flex justify-center text-left"> <div v-if="!needToSetup" class="flex justify-center text-left">
<div v-if="currentContract" class="sm:w-2/3"> <div v-if="currentContract" class="sm:w-2/3">
<ContractTab v-if="currentTab === 'contract'" :contract="currentContract" /> <ContractTab v-if="currentTab === 'contract'" :contract="currentContract" />
<ClientTab v-if="currentTab === 'client'" :contract="currentContract" /> <ClientTab v-if="currentTab === 'client'" :contract="currentContract" />
<CommentsTab v-if="currentTab === 'comments'" :contract="currentContract" /> <CommentsTab v-if="currentTab === 'comments'" :contract="currentContract" />
</div> </div>
</div> </div>
<div class="flex justify-center">
<div v-if="needToSetup" class="sm:w-2/3 max-sm:w-full">
<p v-for="error of v$.$errors" :key="error.$uid" class="text-red-900">
<strong>{{ error.$message }}</strong>
</p>
<div class="pt-3">
<label
for="base-input"
class="text-left block mb-2 text-sm font-medium text-gray-900 dark:text-white"
>Name</label
>
<input
id="base-input"
v-model="name"
type="text"
required
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" />
</div>
<div class="pt-3">
<label
for="base-input"
required
class="text-left block mb-2 text-sm font-medium text-gray-900 dark:text-white"
>Address</label
>
<input
id="base-input"
v-model="address"
type="text"
required
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" />
</div>
<div class="pt-3">
<label
for="base-input"
class="text-left block mb-2 text-sm font-medium text-gray-900 dark:text-white"
>Anschprechpartner</label
>
<input
id="base-input"
v-model="contact"
type="text"
required
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" />
</div>
<div class="pt-3">
<label
for="base-input"
class="text-left block mb-2 text-sm font-medium text-gray-900 dark:text-white"
>Email</label
>
<input
id="base-input"
v-model="email"
type="email"
required
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" />
</div>
<div class="pt-3">
<label
for="base-input"
class="text-left block mb-2 text-sm font-medium text-gray-900 dark:text-white"
>Phone number</label
>
<input
id="base-input"
v-model="phone"
type="text"
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" />
</div>
<label for="message" class="block mb-2 pt-3 text-sm font-medium text-gray-900 dark:text-white"
>Beschreibung</label
>
<textarea
id="description"
rows="9"
class="block p-2.5 w-full text-sm text-gray-900 bg-gray-50 rounded-lg border border-gray-300 focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
placeholder="Write your thoughts here..."></textarea>
<div class="pt-3">
<label
for="base-input"
class="text-left block mb-2 text-sm font-medium text-gray-900 dark:text-white"
>Beispiele</label
>
<div v-for="(example, counter) in examples" :key="counter" class="sm:flex pt-2">
<input
id="base-input"
v-model="example.name"
type="text"
placeholder="Name"
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" />
<input
id="base-input"
v-model="example.url"
type="text"
placeholder="Link"
class="bg-gray-50 border sm:ml-3 border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" />
<font-awesome-icon icon="fa-solid fa-plus" class="h-6 mt-2 ml-2" @click="addLink" />
<font-awesome-icon
icon="fa-solid fa-trash"
class="h-5 mt-2 ml-2"
@click="deleteLink(counter)" />
</div>
<label
for="base-input"
class="text-left block mb-2 mt-2 text-sm font-medium text-gray-900 dark:text-white"
>Documents</label
>
<div v-for="(document, counter) in documents" :key="counter" class="sm:flex pt-2">
<input
id="base-input"
v-model="document.name"
type="text"
placeholder="Name"
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" />
<input
id="base-input"
v-model="document.url"
type="text"
placeholder="Link"
class="bg-gray-50 border sm:ml-3 border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" />
<font-awesome-icon icon="fa-solid fa-plus" class="h-6 mt-2 ml-2" @click="addDocument" />
<font-awesome-icon
icon="fa-solid fa-trash"
class="h-5 mt-2 ml-2"
@click="deleteDocument(counter)" />
</div>
<button
class="bg-emerald-500 mt-4 text-white active:bg-emerald-600 font-bold uppercase text-normal px-10 py-2 rounded shadow hover:shadow-md outline-none focus:outline-none mr-1 mb-1 ease-linear transition-all duration-150"
type="button"
@click="updateContract">
Save
</button>
</div>
</div>
</div>
</template> </template>
<script> <script>
import Navbar from '../components/Navbar.vue' import Navbar from '../components/Navbar.vue'
@@ -60,6 +196,10 @@ import { mapActions, mapGetters } from 'vuex'
import ClientTab from '../components/tabs/ClientTab.vue' import ClientTab from '../components/tabs/ClientTab.vue'
import ContractTab from '../components/tabs/ContractTab.vue' import ContractTab from '../components/tabs/ContractTab.vue'
import CommentsTab from '../components/tabs/CommentsTab.vue' import CommentsTab from '../components/tabs/CommentsTab.vue'
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome'
import { setupContract } from '../service/ContractsService'
import { useVuelidate } from '@vuelidate/core'
import { required } from '../main'
export default { export default {
components: { components: {
@@ -68,25 +208,97 @@ export default {
ClientTab, ClientTab,
Navbar Navbar
}, },
setup() {
return {
v$: useVuelidate()
}
},
validations() {
return {
name: { required },
address: { required },
contact: { required },
email: { required },
phone: { required }
}
},
data() { data() {
return { return {
currentTab: 'contract' currentTab: 'contract',
needToSetup: false,
name: '',
address: '',
contact: '',
email: '',
phone: '',
description: '',
examples: [
{
name: '',
url: ''
}
],
documents: [
{
name: '',
url: ''
}
]
} }
}, },
computed: { computed: {
...mapGetters(['currentContract']) ...mapGetters(['currentContract'])
}, },
mounted() { async mounted() {
const id = this.$route.query.id const id = this.$route.query.id
if (id === null) { if (id === null) {
this.$router.push('/error?message=' + 'Bad id' + '&code=404') //TODO: check if works this.$router.push('/error?message=' + 'Bad id' + '&code=404') //TODO: check if works
} }
this.fetchContractById(id, this.$store.state.keycloak.keycloak.token) await this.fetchContractById(id, this.$store.state.keycloak.keycloak.token)
if (this.currentContract.client === null) {
this.currentTab = ''
this.needToSetup = true
}
}, },
methods: { methods: {
...mapActions(['fetchContractById']), ...mapActions(['openModal', 'fetchContractById']),
changeTab(tabName) { changeTab(tabName) {
this.currentTab = tabName this.currentTab = tabName
},
addLink() {
this.examples.push({
name: '',
url: ''
})
},
deleteLink(counter) {
this.examples.splice(counter, 1)
},
addDocument() {
this.documents.push({
name: '',
url: ''
})
},
deleteDocument(counter) {
this.documents.splice(counter, 1)
},
async updateContract() {
const isFormCorrect = await this.v$.$validate()
if (!isFormCorrect) return
await setupContract(this.$route.query.id, {
name: this.name,
address: this.address,
contact: this.contact,
email: this.email,
phone: this.phone,
description: this.description,
examples: this.examples,
documents: this.documents
})
this.$router.go()
} }
} }
} }