diff --git a/src/main/java/de/champonthis/abi/buisinesslogic/ContactDataManager.java b/src/main/java/de/champonthis/abi/buisinesslogic/ContactDataManager.java index 0c77c58..3a3853e 100644 --- a/src/main/java/de/champonthis/abi/buisinesslogic/ContactDataManager.java +++ b/src/main/java/de/champonthis/abi/buisinesslogic/ContactDataManager.java @@ -25,6 +25,10 @@ public class ContactDataManager { return contactDataRepository.findByContactAndReportedBy(contact, reportedBy).orElse(null); } + public ContactData findByContactAndEmail(Long contact, String email) { + return contactDataRepository.findByContactAndEmail(contact, email).orElse(null); + } + public ContactData findByinviteToken(String inviteToken) { return contactDataRepository.findByinviteToken(inviteToken).orElse(null); } diff --git a/src/main/java/de/champonthis/abi/controller/ContactDataController.java b/src/main/java/de/champonthis/abi/controller/ContactDataController.java index 666dcc4..bb172e1 100644 --- a/src/main/java/de/champonthis/abi/controller/ContactDataController.java +++ b/src/main/java/de/champonthis/abi/controller/ContactDataController.java @@ -65,7 +65,11 @@ public class ContactDataController { inviteToken = ContactManager.generateToken(); } contactData.setInviteToken(inviteToken); - contactDataManager.sendInviteMail(contact, contactData, reportedBy); + + if (contactDataManager.findByContactAndEmail(contact.getId(), contactData.getEmail()) == null) { + contactDataManager.sendInviteMail(contact, contactData, reportedBy); + } + sendToken = false; } contactDataManager.save(contactData); diff --git a/src/main/java/de/champonthis/abi/controller/FrontendController.java b/src/main/java/de/champonthis/abi/controller/FrontendController.java index 9d9694c..85eb3ce 100644 --- a/src/main/java/de/champonthis/abi/controller/FrontendController.java +++ b/src/main/java/de/champonthis/abi/controller/FrontendController.java @@ -33,7 +33,7 @@ public class FrontendController { model.addAttribute("token", token); model.addAttribute("userName", contact.getName()); model.addAttribute("altName", contact.getUpdatedName()); - model.addAttribute("altName", contact.getUpdatedName()); + model.addAttribute("committed", contact.getCommitted()); ContactData contactData = contactDataManager.findByContactAndReportedBy(contact.getId(), contact.getId()); diff --git a/src/main/java/de/champonthis/abi/repository/ContactDataRepository.java b/src/main/java/de/champonthis/abi/repository/ContactDataRepository.java index 7b9417b..4d85c5d 100644 --- a/src/main/java/de/champonthis/abi/repository/ContactDataRepository.java +++ b/src/main/java/de/champonthis/abi/repository/ContactDataRepository.java @@ -12,5 +12,7 @@ public interface ContactDataRepository extends JpaRepository Optional findByContactAndReportedBy(Long contact, Long reportedBy); + Optional findByContactAndEmail(Long contact, String email); + Optional findByinviteToken(String inviteToken); } diff --git a/src/main/resources/static/css/style.css b/src/main/resources/static/style.css similarity index 100% rename from src/main/resources/static/css/style.css rename to src/main/resources/static/style.css diff --git a/src/main/resources/templates/email/confirmation.html b/src/main/resources/templates/email/confirmation.html index f32f59f..9daec1c 100644 --- a/src/main/resources/templates/email/confirmation.html +++ b/src/main/resources/templates/email/confirmation.html @@ -9,7 +9,7 @@

Hallo !

- Super, dass du für unser 20-Jahres-Abitreffen am 13.11.2027 zugesagt hast - wir freuen uns sehr, dich dort wiederzusehen! + Super, dass du für unser 20-Jahres-Abitreffen am 13.11.2027 in Gevelsberg zugesagt hast - wir freuen uns sehr, dich dort wiederzusehen!

Schade, dass du im Moment nicht dabei bist. Du kannst deine Meinung aber jederzeit ändern. diff --git a/src/main/resources/templates/index.html b/src/main/resources/templates/index.html index 96c66be..7b04bbc 100644 --- a/src/main/resources/templates/index.html +++ b/src/main/resources/templates/index.html @@ -8,7 +8,7 @@ - + @@ -94,11 +94,12 @@

- + -
+

@@ -123,7 +124,7 @@

-
@@ -187,11 +189,12 @@ class="form-control" autofocus />
- +
-
+
@@ -205,7 +208,7 @@ class="form-control" />
+ :class="{'disabled': working}" autofocus>Speichern
    @@ -215,13 +218,14 @@
- -
@@ -236,22 +240,27 @@ - Schritt 4: Bist du beim 20-Jahrestreffen am 13.11.2027 dabei? + Schritt 4: Bist du beim 20-Jahrestreffen am 13.11.2027 in Gevelsberg dabei? -
-

- Hast du Lust, am Samstag, den 13.11.2027, beim Nachtreffen dabei zu sein? Mehr Infos gibt's - dann hier und per Mail. +

+

+ Hast du Lust, am Samstag, den 13.11.2027, beim Nachtreffen in Gevelsberg dabei zu sein? + Genauere Infos und Details gibt's dann später hier und per Mail.

- - +
-
@@ -268,10 +277,11 @@ return { // Step state step: 1, + stepMsg: '', + stepMsgType: '', + working: false, // Step 1 yourName: '', - step1Msg: '', - step1MsgType: '', altNameChecked: false, altName: '[[${altName}]]', showStep1Continue: false, @@ -281,62 +291,72 @@ // Step 2 email: '[[${email}]]', phone: '[[${phone}]]', - step2Msg: '', - step2MsgType: '', // Step 3 knownContactName: '', knownContactEmail: '', knownContactPhone: '', showKnownContactData: false, enteredContacts: [], - step3Msg: '', - step3MsgType: '', - foundKnownContactName: null, // <-- add this line + foundKnownContactName: null, // Step 4 - step4Msg: '', - step4MsgType: '', + committed: '[[${committed}]]', // Methods async findSelf() { - this.step1Msg = ''; - this.step1MsgType = ''; + this.stepMsg = ''; + this.stepMsgType = ''; this.altNameChecked = false; this.altName = ''; this.pendingUpdatedName = null; try { + this.working = true; const resp = await axios.get(`/api/v1/contact`, { params: { name: this.yourName.trim() }, validateStatus: () => true }); if (resp.status === 200) { this.userName = resp.data.name; this.userToken = resp.data.token || null; } else if (resp.status === 404) { - this.step1Msg = 'Sorry, wir konnten dich nicht finden. Schreib deinen Namen bitte genau so, wie er auf dem Abi-T-Shirt stand!'; - this.step1MsgType = 'warning'; + this.stepMsg = 'Sorry, wir konnten dich nicht finden. Schreib deinen Namen bitte genau so, wie er auf dem Abi-T-Shirt stand!'; + this.stepMsgType = 'warning'; } else if (resp.status === 208) { - this.step1Msg = 'Du hast deine Daten schon eingetragen. Danke dir!'; - this.step1MsgType = 'info'; + this.stepMsg = 'Du hast deine Daten schon eingetragen. Danke dir!'; + this.stepMsgType = 'info'; // Prevent showing greeting/alt name UI this.userName = null; } else { - this.step1Msg = 'Uups, da ist was schiefgelaufen. Versuch es gleich nochmal!'; - this.step1MsgType = 'danger'; + this.stepMsg = 'Uups, da ist was schiefgelaufen. Versuch es gleich nochmal!'; + this.stepMsgType = 'danger'; } } catch { - this.step1Msg = 'Uups, da ist was schiefgelaufen. Versuch es gleich nochmal!'; - this.step1MsgType = 'danger'; + this.stepMsg = 'Uups, da ist was schiefgelaufen. Versuch es gleich nochmal!'; + this.stepMsgType = 'danger'; } + this.working = false; + }, + setStep(step) { + this.stepMsg = ''; + this.stepMsgType = ''; + this.step = step; }, async continueStep1() { this.pendingUpdatedName = this.altNameChecked ? this.altName.trim() : null; if (this.pendingUpdatedName && !this.userToken) { - await axios.post('/api/v1/contact', { - name: this.userName, - updatedName: this.pendingUpdatedName - }); + this.working = true; + try { + await axios.post('/api/v1/contact', { + name: this.userName, + updatedName: this.pendingUpdatedName + }); + } catch { + this.stepMsg = 'Uups, da ist was schiefgelaufen. Versuch es gleich nochmal!'; + this.stepMsgType = 'danger'; + } + this.working = false; } - this.step = 2; + this.setStep(2); }, async submitContactData() { - this.step2Msg = ''; - this.step2MsgType = ''; + this.stepMsg = ''; + this.stepMsgType = ''; + this.working = true; try { const resp = await axios.post('/api/v1/contact/data', { name: this.userName, @@ -345,26 +365,28 @@ phone: this.phone.trim() }, { validateStatus: () => true }); if (resp.status === 200 || resp.status === 201) { - this.step = 3; + this.setStep(3); } else if (resp.status === 400) { - this.step2Msg = 'Bitte schau nochmal über deine Angaben – da stimmt was nicht.'; - this.step2MsgType = 'warning'; + this.stepMsg = 'Bitte schau nochmal über deine Angaben – da stimmt was nicht.'; + this.stepMsgType = 'warning'; } else { - this.step2Msg = 'Da ist was schiefgelaufen. Versuch es bitte nochmal!'; - this.step2MsgType = 'danger'; + this.stepMsg = 'Da ist was schiefgelaufen. Versuch es bitte nochmal!'; + this.stepMsgType = 'danger'; } } catch { - this.step2Msg = 'Da ist was schiefgelaufen. Versuch es bitte nochmal!'; - this.step2MsgType = 'danger'; + this.stepMsg = 'Da ist was schiefgelaufen. Versuch es bitte nochmal!'; + this.stepMsgType = 'danger'; } + this.working = false; }, async findKnownContact() { - this.step3Msg = ''; - this.step3MsgType = ''; + this.stepMsg = ''; + this.stepMsgType = ''; this.showKnownContactData = false; this.knownContactEmail = ''; this.knownContactPhone = ''; - this.foundKnownContactName = null; // reset + this.foundKnownContactName = null; + this.working = true; try { const resp = await axios.get('/api/v1/contact', { params: { name: this.knownContactName.trim() }, @@ -373,35 +395,37 @@ if (resp.status === 200) { this.foundKnownContactName = resp.data.name.trim(); if (this.foundKnownContactName == this.yourName) { - this.step3Msg = 'Das bist du selbst – deine Daten hast du ja schon eingetragen!'; - this.step3MsgType = 'warning'; + this.stepMsg = 'Das bist du selbst – deine Daten hast du ja schon eingetragen!'; + this.stepMsgType = 'warning'; this.showKnownContactData = false; this.knownContactName = '' return; } this.knownContactName = this.foundKnownContactName; - this.step3Msg = 'Super, trag bitte die Kontaktdaten ein!'; - this.step3MsgType = 'success'; + this.stepMsg = 'Super, trag bitte die Kontaktdaten ein!'; + this.stepMsgType = 'success'; this.showKnownContactData = true; } else if (resp.status === 404) { - this.step3Msg = 'Diesen Namen gibt es leider nicht in unserer Liste.'; - this.step3MsgType = 'warning'; + this.stepMsg = 'Diesen Namen gibt es leider nicht in unserer Liste.'; + this.stepMsgType = 'warning'; } else if (resp.status === 208) { - this.step3Msg = 'Für diese Person haben wir schon Kontaktdaten. Danke trotzdem fürs Mitmachen!'; - this.step3MsgType = 'info'; + this.stepMsg = 'Für diese Person haben wir schon Kontaktdaten. Danke trotzdem fürs Mitmachen!'; + this.stepMsgType = 'info'; this.showKnownContactData = false; } else { - this.step3Msg = 'Da ist was schiefgelaufen. Versuch es bitte nochmal!'; - this.step3MsgType = 'danger'; + this.stepMsg = 'Da ist was schiefgelaufen. Versuch es bitte nochmal!'; + this.stepMsgType = 'danger'; } } catch { - this.step3Msg = 'Da ist was schiefgelaufen. Versuch es bitte nochmal!'; - this.step3MsgType = 'danger'; + this.stepMsg = 'Da ist was schiefgelaufen. Versuch es bitte nochmal!'; + this.stepMsgType = 'danger'; } + this.working = false; }, async submitKnownContactData() { - this.step3Msg = ''; - this.step3MsgType = ''; + this.stepMsg = ''; + this.stepMsgType = ''; + this.working = true; try { const resp = await axios.post('/api/v1/contact/data', { name: this.foundKnownContactName, @@ -416,45 +440,49 @@ email: this.knownContactEmail.trim(), phone: this.knownContactPhone.trim() }); - this.step3Msg = 'Danke, die Kontaktdaten sind gespeichert! Du kannst noch mehr eintragen oder einfach weitermachen.'; - this.step3MsgType = 'success'; + this.stepMsg = 'Danke, die Kontaktdaten sind gespeichert! Du kannst noch mehr eintragen oder einfach weitermachen.'; + this.stepMsgType = 'success'; this.showKnownContactData = false; this.knownContactName = ''; this.foundKnownContactName = null; } else if (resp.status === 400) { - this.step3Msg = 'Bitte prüfe die Angaben nochmal – da stimmt was nicht.'; - this.step3MsgType = 'warning'; + this.stepMsg = 'Bitte prüfe die Angaben nochmal – da stimmt was nicht.'; + this.stepMsgType = 'warning'; } else { - this.step3Msg = 'Da ist was schiefgelaufen. Versuch es bitte nochmal!'; - this.step3MsgType = 'danger'; + this.stepMsg = 'Da ist was schiefgelaufen. Versuch es bitte nochmal!'; + this.stepMsgType = 'danger'; } } catch { - this.step3Msg = 'Da ist was schiefgelaufen. Versuch es bitte nochmal!'; - this.step3MsgType = 'danger'; + this.stepMsg = 'Da ist was schiefgelaufen. Versuch es bitte nochmal!'; + this.stepMsgType = 'danger'; } + this.working = false; }, async submitCommit(committed) { + this.working = true; + this.committed = committed; try { await axios.post('/api/v1/contact', { name: this.userName, updatedName: this.pendingUpdatedName, token: this.userToken, - committed: committed + committed: this.committed }, { headers: this.userToken ? { 'Authorization': this.userToken } : {} }); - if (committed == 'YES') { - this.step4Msg = 'Danke für deine Rückmeldung! Schön, dass du dabei bist! Wir melden uns rechtzeitig mit allen weiteren Infos.' + (this.userToken ? '' : ' Du solltest schon automatisch eine E-Mail mit einem Link bekommen haben, über den du deine Daten jederzeit anpassen kannst.'); - this.step4MsgType = 'success'; - } else { - this.step4Msg = 'Danke für deine Rückmeldung! Schade, dass du nicht dabei bist.' + (this.userToken ? '' : ' Du solltest trotzdem automatisch eine E-Mail mit einem Link bekommen haben, über den du deine Daten jederzeit anpassen kannst und auch noch zusagen kannst, solltest du doch noch kommen wollen.'); - this.step4MsgType = 'info'; + if (this.committed == 'YES') { + this.stepMsg = 'Danke für deine Rückmeldung! Schön, dass du dabei bist! Wir melden uns rechtzeitig mit allen weiteren Infos.' + (this.userToken ? '' : ' Du solltest schon automatisch eine E-Mail mit einem Link bekommen haben, über den du deine Daten jederzeit anpassen kannst.'); + this.stepMsgType = 'success'; + } else if (this.committed == 'NO') { + this.stepMsg = 'Danke für deine Rückmeldung! Schade, dass du nicht dabei bist.' + (this.userToken ? '' : ' Du solltest trotzdem automatisch eine E-Mail mit einem Link bekommen haben, über den du deine Daten jederzeit anpassen kannst und auch noch zusagen kannst, solltest du doch noch kommen wollen.'); + this.stepMsgType = 'info'; } } catch { - this.step4Msg = 'Da ist was schiefgelaufen. Versuch es bitte nochmal!'; - this.step4MsgType = 'danger'; + this.stepMsg = 'Da ist was schiefgelaufen. Versuch es bitte nochmal!'; + this.stepMsgType = 'danger'; } + this.working = false; } } }