Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 3 additions & 5 deletions backend/src/models/contact.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import (

type ContactPhone struct {
Phone string `json:"phone" bson:"phone"`
Valid bool `json:"valid" bson:"valid"`
}

type ContactSocials struct {
Expand All @@ -22,7 +21,6 @@ type ContactSocials struct {
type ContactMail struct {
Mail string `json:"mail" bson:"mail"`
Personal bool `json:"personal" bson:"personal"`
Valid bool `json:"valid" bson:"valid"`
}

type Gender string
Expand Down Expand Up @@ -51,11 +49,11 @@ type Contact struct {
Mails []ContactMail `json:"mails" bson:"mails"`
}

// HasPhone (phone) returns true if contact has a valid phone
// HasPhone (phone) returns true if contact has a phone
// number that is a case insensitive partial match to `phone`
func (c *Contact) HasPhone(p string) bool {
for _, s := range c.Phones {
if strings.Contains(strings.ToLower(s.Phone), strings.ToLower(p)) && s.Valid {
if strings.Contains(strings.ToLower(s.Phone), strings.ToLower(p)) {
return true
}
}
Expand All @@ -66,7 +64,7 @@ func (c *Contact) HasPhone(p string) bool {
// that is a case insensitive partial match to `mail`
func (c *Contact) HasMail(m string) bool {
for _, s := range c.Mails {
if strings.Contains(strings.ToLower(s.Mail), strings.ToLower(m)) && s.Valid {
if strings.Contains(strings.ToLower(s.Mail), strings.ToLower(m)) {
return true
}
}
Expand Down
4 changes: 0 additions & 4 deletions backend/src/router/contacts_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ var (
Contact1 *models.Contact
Contact1Phone = models.ContactPhone{
Phone: "1",
Valid: true,
}
Contact1Socials = models.ContactSocials{
Facebook: "facebook",
Expand All @@ -29,7 +28,6 @@ var (
Contact1Mail = models.ContactMail{
Mail: "2",
Personal: true,
Valid: true,
}
Contact1Data = mongodb.CreateContactData{
Phones: append(make([]models.ContactPhone, 0), Contact1Phone),
Expand All @@ -39,7 +37,6 @@ var (
Contact2 *models.Contact
Contact2Phone = models.ContactPhone{
Phone: "3",
Valid: true,
}
Contact2Socials = models.ContactSocials{
Facebook: "facebook2",
Expand All @@ -51,7 +48,6 @@ var (
Contact2Mail = models.ContactMail{
Mail: "4",
Personal: true,
Valid: true,
}
Contact2Data = mongodb.CreateContactData{
Phones: append(make([]models.ContactPhone, 0), Contact2Phone),
Expand Down
21 changes: 1 addition & 20 deletions frontend/src/components/ContactCard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -122,24 +122,14 @@
<ClipboardIcon class="w-4 h-4" />
</template>
</Button>
<div
v-if="mail.personal || !mail.valid"
class="flex gap-1 flex-shrink-0"
>
<div v-if="mail.personal" class="flex gap-1 flex-shrink-0">
<Badge
v-if="mail.personal"
variant="secondary"
class="text-xs"
>
Personal
</Badge>
<Badge
v-if="!mail.valid"
variant="destructive"
class="text-xs"
>
Invalid
</Badge>
</div>
</div>
<div v-if="copyError" class="text-xs text-destructive mt-1">
Expand Down Expand Up @@ -168,15 +158,6 @@
>
{{ phone.phone }}
</a>
<div v-if="!phone.valid" class="flex gap-1 flex-shrink-0">
<Badge
v-if="!phone.valid"
variant="destructive"
class="text-xs"
>
Invalid
</Badge>
</div>
</div>
</div>
</div>
Expand Down
110 changes: 47 additions & 63 deletions frontend/src/components/ParticipationsCard.vue
Original file line number Diff line number Diff line change
@@ -1,63 +1,44 @@
<template>
<Card class="w-full py-0">
<CardHeader class="w-full">
<Accordion type="single" collapsible class="w-full">
<AccordionItem value="participations">
<AccordionTrigger class="text-lg font-semibold px-0 cursor-pointer">
Participations
</AccordionTrigger>
<AccordionContent class="px-0">
<div
v-if="sortedParticipations.length === 0"
class="text-muted-foreground p-4"
>
No participations found.
</div>
<div v-else class="space-y-4">
<!-- Current participation - Editable or Create -->
<div v-if="currentParticipation">
<div class="flex items-center gap-2 mb-3">
<h4 class="text-sm font-medium text-muted-foreground">
Current
</h4>
</div>
<EditableCompanyParticipation
v-if="isCompanyParticipation(currentParticipation)"
:participation="currentParticipation"
:company-id="entityId"
/>
<EditableSpeakerParticipation
v-else-if="isSpeakerParticipation(currentParticipation)"
:participation="currentParticipation"
:speaker-id="entityId"
/>
</div>

<!-- Create participation if no current participation exists -->
<div v-else-if="getCurrentEvent()">
<div class="flex items-center gap-2 mb-3">
<h4 class="text-sm font-medium text-muted-foreground">
Current
</h4>
</div>

<EmptyStateCard
title="Create Participation"
:description="`Click to participate in ${getEventName(getCurrentEvent()?.id || 0)}`"
:loading="isCreatingParticipation"
loading-text="Creating..."
@click="createParticipation"
/>
</div>

<!-- Past participations - Read-only -->
<div v-if="pastParticipations.length > 0">
<h4
v-if="currentParticipation || getCurrentEvent()"
class="text-sm font-medium text-muted-foreground mb-3 mt-6"
>
Past Participations
</h4>
<CardHeader :class="['pt-6', { 'pb-6': pastParticipations.length === 0 }]">
<h2 class="text-lg font-semibold mb-4">Participations</h2>
<div v-if="sortedParticipations.length > 0" class="space-y-4">
<div v-if="currentParticipation">
<div class="flex items-center gap-2 mb-3">
<h4 class="text-sm font-medium text-muted-foreground">Current</h4>
</div>
<EditableCompanyParticipation
v-if="isCompanyParticipation(currentParticipation)"
:participation="currentParticipation"
:company-id="entityId"
/>
<EditableSpeakerParticipation
v-else-if="isSpeakerParticipation(currentParticipation)"
:participation="currentParticipation"
:speaker-id="entityId"
/>
</div>
<div v-else-if="getCurrentEvent()">
<div class="flex items-center gap-2 mb-3">
<h4 class="text-sm font-medium text-muted-foreground">Current</h4>
</div>
<EmptyStateCard
title="Create Participation"
:description="`Click to participate in ${getEventName(getCurrentEvent()?.id || 0)}`"
:loading="isCreatingParticipation"
loading-text="Creating..."
@click="createParticipation"
/>
</div>
<div v-if="pastParticipations.length > 0">
<Accordion type="single" collapsible class="w-full">
<AccordionItem value="pastParticipations">
<AccordionTrigger
class="text-sm font-semibold px-0 cursor-pointer"
>
Past Participations
</AccordionTrigger>
<AccordionContent class="px-0 pt-4">
<div class="space-y-4">
<Card
v-for="participation in pastParticipations"
Expand Down Expand Up @@ -138,11 +119,14 @@
</div>
</Card>
</div>
</div>
</div>
</AccordionContent>
</AccordionItem>
</Accordion>
</AccordionContent>
</AccordionItem>
</Accordion>
</div>
</div>
<div v-else class="text-muted-foreground p-4">
No participations found.
</div>
</CardHeader>
</Card>
</template>
Expand Down
100 changes: 52 additions & 48 deletions frontend/src/components/cards/WorkflowCard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -78,65 +78,69 @@ watch(
</script>

<template>
<Card
:class="[
'ring',
'h-full',
'relative',
participationStatusColor[selectedStatus].ring,
]"
<component
:is="props.to ? 'RouterLink' : 'div'"
:to="props.to"
:class="['block', props.to ? 'cursor-pointer' : '']"
>
<!-- Confetti explosion for accepted/announced states -->
<div
v-if="showConfetti"
class="absolute left-1/2 top-1/2 pointer-events-none z-50 -translate-x-1/2 -translate-y-1/2"
<Card
:class="[
'ring',
'h-full',
'relative',
participationStatusColor[selectedStatus].ring,
]"
>
<ConfettiExplosion />
</div>
<div
v-if="showConfetti"
class="absolute left-1/2 top-1/2 pointer-events-none z-50 -translate-x-1/2 -translate-y-1/2"
>
<ConfettiExplosion />
</div>

<CardContent>
<Select v-model="selectedStatus" class="relative z-10">
<SelectTrigger
<CardContent>
<div
v-if="!possibleStates.length"
:class="[
'w-full',
'w-full flex items-center rounded-md border bg-transparent px-3 py-2 text-sm shadow-xs pointer-events-none',
participationStatusColor[selectedStatus].background,
]"
>
<SelectValue placeholder="State">
{{ humanReadableParticipationStatus[selectedStatus] }}
</SelectValue>
</SelectTrigger>
<SelectContent v-if="possibleStates.length">
<SelectItem
v-for="(state, i) in possibleStates"
:key="state"
:value="i + 1"
{{ humanReadableParticipationStatus[selectedStatus] }}
</div>
<Select v-else v-model="selectedStatus" class="relative z-10">
<SelectTrigger
:class="[
'w-full',
participationStatusColor[selectedStatus].background,
]"
>
{{ humanReadableParticipationStatus[state] }}
</SelectItem>
</SelectContent>
</Select>
<SelectValue placeholder="State">
{{ humanReadableParticipationStatus[selectedStatus] }}
</SelectValue>
</SelectTrigger>
<SelectContent>
<SelectItem
v-for="(state, i) in possibleStates"
:key="state"
:value="i + 1"
>
{{ humanReadableParticipationStatus[state] }}
</SelectItem>
</SelectContent>
</Select>

<component
:is="props.to ? 'RouterLink' : 'div'"
:to="props.to"
:class="['block w-full', props.to ? 'cursor-pointer' : '']"
>
<Image
:src="image"
class="w-full h-32 object-contain rounded-lg pt-2"
/>
</component>
</CardContent>
<component
:is="props.to ? 'RouterLink' : 'div'"
:to="props.to"
:class="['block', props.to ? 'cursor-pointer' : '']"
>
<div class="block w-full">
<Image
:src="image"
class="w-full h-32 object-contain rounded-lg pt-2"
/>
</div>
</CardContent>
<CardHeader>
<CardTitle>{{ title }}</CardTitle>
<Badge v-if="badge">{{ badge }}</Badge>
</CardHeader>
</component>
</Card>
</Card>
</component>
</template>
12 changes: 6 additions & 6 deletions frontend/src/components/companies/ContactForm.vue
Original file line number Diff line number Diff line change
Expand Up @@ -316,8 +316,8 @@ const formData = reactive<Required<CreateCompanyRepData>>({
contact: {
gender: undefined,
language: undefined,
mails: [{ mail: "", personal: false, valid: true }],
phones: [{ phone: "", valid: true }],
mails: [{ mail: "", personal: false }],
phones: [{ phone: "" }],
socials: {
linkedin: "",
twitter: "",
Expand All @@ -339,11 +339,11 @@ watch(
formData.contact.mails =
newData.contact.mails.length > 0
? [...newData.contact.mails]
: [{ mail: "", personal: false, valid: true }];
: [{ mail: "", personal: false }];
formData.contact.phones =
newData.contact.phones.length > 0
? [...newData.contact.phones]
: [{ phone: "", valid: true }];
: [{ phone: "" }];
formData.contact.socials = { ...newData.contact.socials };
}
},
Expand All @@ -370,15 +370,15 @@ const validationMessage = computed(() => {
});

const addEmail = () => {
formData.contact.mails.push({ mail: "", personal: false, valid: true });
formData.contact.mails.push({ mail: "", personal: false });
};

const removeEmail = (index: number) => {
formData.contact.mails.splice(index, 1);
};

const addPhone = () => {
formData.contact.phones.push({ phone: "", valid: true });
formData.contact.phones.push({ phone: "" });
};

const removePhone = (index: number) => {
Expand Down
Loading