From b9d8c8b251b9f9a5c4a2d13ef15f9b73f11ae0bd Mon Sep 17 00:00:00 2001 From: joao vitor lobo Date: Sat, 24 Jan 2026 23:44:22 +0000 Subject: [PATCH 1/6] fix: 3 issues at once --- backend/src/mongodb/speaker.go | 4 +- frontend/public/templates/speakers/33-pt.html | 1226 +++++++---------- .../src/components/BulkEmailDialogTrigger.vue | 8 +- frontend/src/components/Communications.vue | 36 +- .../src/components/companies/ContactForm.vue | 4 +- .../components/speakers/CreateSpeakerForm.vue | 14 +- .../speakers/SpeakerCommunications.vue | 13 +- frontend/src/composables/useBulkEmails.ts | 16 +- frontend/src/composables/useDirectEmail.ts | 9 +- frontend/src/dto/speakers.ts | 3 + frontend/src/lib/templates.ts | 90 +- .../views/Dashboard/ResponsibilitiesView.vue | 4 +- 12 files changed, 668 insertions(+), 759 deletions(-) diff --git a/backend/src/mongodb/speaker.go b/backend/src/mongodb/speaker.go index b35e7fe0..a2e0ab66 100644 --- a/backend/src/mongodb/speaker.go +++ b/backend/src/mongodb/speaker.go @@ -127,7 +127,9 @@ func (s *SpeakersType) CreateSpeaker(data CreateSpeakerData) (*models.Speaker, e ctx := context.Background() contact := bson.M{ - "phones": []models.ContactPhone{}, + "gender": data.Contact.Gender, + "language": data.Contact.Language, + "phones": []models.ContactPhone{}, "socials": bson.M{ "facebook": "", "skype": "", diff --git a/frontend/public/templates/speakers/33-pt.html b/frontend/public/templates/speakers/33-pt.html index 6a195f66..fdf85e8b 100644 --- a/frontend/public/templates/speakers/33-pt.html +++ b/frontend/public/templates/speakers/33-pt.html @@ -1,169 +1,164 @@ - - - - - - - - SINFO {{.Edition}} - Convite para participação como orador! - - - - - - + + + - - - - - - - - - + +
-
- -
+ + + + +
+
+ +
- Em nome da equipa que organiza a SINFO, ficaríamos muito felizes - se aceitasse o nosso convite para fazer uma palestra. A SINFO é - uma organização de estudantes universitários sem fins lucrativos - responsável pelo planeamento de um dos maiores eventos de - tecnologia em Portugal. Trata-se de uma conferência anual que - ocorre em Lisboa. -
- - - - - - - - - - + + +
+
+ + + + \ No newline at end of file diff --git a/frontend/src/components/BulkEmailDialogTrigger.vue b/frontend/src/components/BulkEmailDialogTrigger.vue index 31adcccb..d02edcff 100644 --- a/frontend/src/components/BulkEmailDialogTrigger.vue +++ b/frontend/src/components/BulkEmailDialogTrigger.vue @@ -450,7 +450,7 @@ import { import { humanReadableParticipationStatus } from "@/dto/index"; import type { ParticipationStatus } from "@/dto/index"; import type { CompanyWithParticipation } from "@/dto/companies"; -import type { SpeakerWithParticipation } from "@/dto/speakers"; +import type { SpeakerWithContactAndParticipation } from "@/dto/speakers"; import { useBulkCompanyEmails, useBulkSpeakerEmails, @@ -462,7 +462,7 @@ interface Props { size?: "sm" | "default" | "lg" | "icon"; buttonClass?: string; companies?: CompanyWithParticipation[]; - speakers?: SpeakerWithParticipation[]; + speakers?: SpeakerWithContactAndParticipation[]; entityType: "companies" | "speakers"; } @@ -499,7 +499,7 @@ const speakerBulk = useBulkSpeakerEmails(); const processBulkEmails = async ( templateCategory: EmailTemplateCategory, statuses: ParticipationStatus[], - entities: CompanyWithParticipation[] | SpeakerWithParticipation[], + entities: CompanyWithParticipation[] | SpeakerWithContactAndParticipation[], ) => { if (props.entityType === "companies") { return companyBulk.processBulkEmails( @@ -511,7 +511,7 @@ const processBulkEmails = async ( return speakerBulk.processBulkEmails( templateCategory, statuses, - entities as SpeakerWithParticipation[], + entities as SpeakerWithContactAndParticipation[], ); }; diff --git a/frontend/src/components/Communications.vue b/frontend/src/components/Communications.vue index eb57b389..8e5ef8d2 100644 --- a/frontend/src/components/Communications.vue +++ b/frontend/src/components/Communications.vue @@ -210,18 +210,6 @@ {{ getKindLabel(thread.kind) }}
-
-
-
- - {{ formatDate(thread.posted) }} - -
{ } }; +const getStatusLabel = (status: ThreadStatus): string => { + switch (status) { + case ThreadStatus.ThreadStatusApproved: + return "Approved"; + case ThreadStatus.ThreadStatusReviewed: + return "Reviewed"; + case ThreadStatus.ThreadStatusPending: + return "Pending"; + default: + return "Unknown"; + } +}; + const getStatusColor = (status: ThreadStatus): string => { switch (status) { case ThreadStatus.ThreadStatusApproved: @@ -1057,7 +1049,7 @@ const getStatusColor = (status: ThreadStatus): string => { default: return "bg-gray-400"; } -}; +};*/ const formatDate = (dateString: string): string => { const date = new Date(dateString); diff --git a/frontend/src/components/companies/ContactForm.vue b/frontend/src/components/companies/ContactForm.vue index 67d7a877..95ab0104 100644 --- a/frontend/src/components/companies/ContactForm.vue +++ b/frontend/src/components/companies/ContactForm.vue @@ -16,7 +16,7 @@
- +
- +
-
@@ -257,6 +260,13 @@ const isStep1Valid = computed(() => { ); }); +const isStep3Valid = computed(() => { + return ( + contactData.value.gender != undefined && + contactData.value.language != undefined + ); +}); + // Step navigation const nextStep = () => { if (currentStep.value === 1 && validateStep1()) { @@ -319,6 +329,8 @@ const createSpeakerAndFinish = async () => { (phone) => phone.phone && phone.phone.trim().length > 0, ), socials: contactData.value.socials || {}, + gender: contactData.value.gender, + language: contactData.value.language, }; const createData: CreateSpeakerData = { diff --git a/frontend/src/components/speakers/SpeakerCommunications.vue b/frontend/src/components/speakers/SpeakerCommunications.vue index 1d8fb89d..4737af5c 100644 --- a/frontend/src/components/speakers/SpeakerCommunications.vue +++ b/frontend/src/components/speakers/SpeakerCommunications.vue @@ -13,7 +13,7 @@ - - - \ No newline at end of file + " + class="center-on-narrow" + > + João Rosário
+ Apple
+
+
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + From d4659537293ea05d7aa3902ccd7ef86e4cd6d47c Mon Sep 17 00:00:00 2001 From: joao vitor lobo Date: Tue, 27 Jan 2026 22:44:52 +0000 Subject: [PATCH 3/6] fix: comments and template number --- frontend/src/components/Communications.vue | 26 ------------------- .../speakers/SpeakerCommunications.vue | 3 --- frontend/src/lib/templates.ts | 4 +-- 3 files changed, 1 insertion(+), 32 deletions(-) diff --git a/frontend/src/components/Communications.vue b/frontend/src/components/Communications.vue index 8e5ef8d2..ab22973f 100644 --- a/frontend/src/components/Communications.vue +++ b/frontend/src/components/Communications.vue @@ -1025,32 +1025,6 @@ const getKindColor = (kind: ThreadKind): string => { } }; -const getStatusLabel = (status: ThreadStatus): string => { - switch (status) { - case ThreadStatus.ThreadStatusApproved: - return "Approved"; - case ThreadStatus.ThreadStatusReviewed: - return "Reviewed"; - case ThreadStatus.ThreadStatusPending: - return "Pending"; - default: - return "Unknown"; - } -}; - -const getStatusColor = (status: ThreadStatus): string => { - switch (status) { - case ThreadStatus.ThreadStatusApproved: - return "bg-green-500"; - case ThreadStatus.ThreadStatusReviewed: - return "bg-yellow-500"; - case ThreadStatus.ThreadStatusPending: - return "bg-red-500"; - default: - return "bg-gray-400"; - } -};*/ - const formatDate = (dateString: string): string => { const date = new Date(dateString); const now = new Date(); diff --git a/frontend/src/components/speakers/SpeakerCommunications.vue b/frontend/src/components/speakers/SpeakerCommunications.vue index 4737af5c..3dfe9b17 100644 --- a/frontend/src/components/speakers/SpeakerCommunications.vue +++ b/frontend/src/components/speakers/SpeakerCommunications.vue @@ -44,9 +44,6 @@ const createSpeakerTemplateVariables = () => { const memberGender = authStore.member!.contactObject.gender; const speakerGender = props.speaker.contactObject.gender; - // Use contactObject which contains the full Contact (including gender) - // Fallback to empty string when gender is unavailable to avoid runtime errors - return [ createEmailVariable.memberArticle(memberGender), createEmailVariable.memberSuffix(memberGender), diff --git a/frontend/src/lib/templates.ts b/frontend/src/lib/templates.ts index 6f1743ff..eebb558f 100644 --- a/frontend/src/lib/templates.ts +++ b/frontend/src/lib/templates.ts @@ -372,10 +372,8 @@ const genderToArticleSuffix = ( return { article: "o", suffix: "" }; case "FEMALE": return { article: "a", suffix: "a" }; - case "OTHER": - return { article: "e", suffix: "e" }; default: - return { article: "o/a/e", suffix: "(a)" }; + return { article: "e", suffix: "e" }; } }; From 20f18f636ae3fe58d128c442a6cf2056c2984659 Mon Sep 17 00:00:00 2001 From: joao vitor lobo Date: Wed, 28 Jan 2026 16:09:57 +0000 Subject: [PATCH 4/6] fix: validation in ContactForm --- .../src/components/companies/ContactForm.vue | 36 +++++++++++++++---- .../components/speakers/CreateSpeakerForm.vue | 6 +++- 2 files changed, 34 insertions(+), 8 deletions(-) diff --git a/frontend/src/components/companies/ContactForm.vue b/frontend/src/components/companies/ContactForm.vue index 95ab0104..508251e8 100644 --- a/frontend/src/components/companies/ContactForm.vue +++ b/frontend/src/components/companies/ContactForm.vue @@ -237,6 +237,18 @@ {{ showMoreSocials ? "- Less" : "+ More" }} social platforms + + +
+

+ {{ validationMessage }} +

+
@@ -350,20 +362,29 @@ watch( { immediate: true }, ); -watch( - () => formData, - (newData) => emit("updated", newData), - { deep: true, immediate: true }, -); - const isValid = computed(() => { const hasName = props.withoutName || formData.name?.trim(); const hasEmail = formData.contact.mails.some((mail) => mail.mail.trim()); - return hasName && hasEmail; + const hasGender = !!formData.contact.gender; + const hasLanguage = !!formData.contact.language; + + return hasName && hasEmail && hasGender && hasLanguage; }); +watch( + () => formData, + (newData) => { + if (isValid.value) { + emit("updated", newData); + } + }, + { deep: true, immediate: true }, +); + const validationMessage = computed(() => { if (!props.withoutName && !formData.name?.trim()) return "Name is required"; + if (!formData.contact.gender) return "Gender is required"; + if (!formData.contact.language) return "Language is required"; if (!formData.contact.mails.some((mail) => mail.mail.trim())) return "At least one email is required"; return ""; @@ -386,6 +407,7 @@ const removePhone = (index: number) => { }; const handleSubmit = () => { + console.log("isValid", isValid.value); if (!isValid.value) return; // Clean up empty fields diff --git a/frontend/src/components/speakers/CreateSpeakerForm.vue b/frontend/src/components/speakers/CreateSpeakerForm.vue index 30d2ec82..22b9811b 100644 --- a/frontend/src/components/speakers/CreateSpeakerForm.vue +++ b/frontend/src/components/speakers/CreateSpeakerForm.vue @@ -263,7 +263,11 @@ const isStep1Valid = computed(() => { const isStep3Valid = computed(() => { return ( contactData.value.gender != undefined && - contactData.value.language != undefined + contactData.value.language != undefined && + contactData.value.mails && + contactData.value.mails.some( + (mail) => mail.mail && mail.mail.trim().length > 0, + ) ); }); From 79414398f9dba014809ce350a4afd1a3d0b88c36 Mon Sep 17 00:00:00 2001 From: joao vitor lobo Date: Wed, 28 Jan 2026 16:23:20 +0000 Subject: [PATCH 5/6] fix: validation in ContactForm --- frontend/src/components/companies/ContactForm.vue | 1 - 1 file changed, 1 deletion(-) diff --git a/frontend/src/components/companies/ContactForm.vue b/frontend/src/components/companies/ContactForm.vue index 508251e8..26e3400e 100644 --- a/frontend/src/components/companies/ContactForm.vue +++ b/frontend/src/components/companies/ContactForm.vue @@ -407,7 +407,6 @@ const removePhone = (index: number) => { }; const handleSubmit = () => { - console.log("isValid", isValid.value); if (!isValid.value) return; // Clean up empty fields From 257486d248f5c670dd8d7ed0d1d487c8f842cfe0 Mon Sep 17 00:00:00 2001 From: joao vitor lobo Date: Mon, 21 Sep 2026 15:58:37 +0100 Subject: [PATCH 6/6] fix: email not required --- frontend/src/components/companies/ContactForm.vue | 7 ++----- frontend/src/components/speakers/CreateSpeakerForm.vue | 6 +----- 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/frontend/src/components/companies/ContactForm.vue b/frontend/src/components/companies/ContactForm.vue index 26e3400e..d3d6a288 100644 --- a/frontend/src/components/companies/ContactForm.vue +++ b/frontend/src/components/companies/ContactForm.vue @@ -60,7 +60,7 @@
- +