Skip to content
Merged
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
33 changes: 33 additions & 0 deletions src/app/plugins/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -2162,6 +2162,39 @@
"addPrompt": "Add prompt",
"removePrompt": "Remove prompt",
"duration": "Minutes"
},
"dashboard": {
"typeLabel": "Focus Group",
"subtitle": "Manage your discussion guide, participants, and moderated sessions from one dashboard."
},
"studyOverview": {
"topics": "Discussion Topics",
"topicsSubtitle": "In the guide",
"totalDuration": "Total Duration",
"durationSubtitle": "Planned",
"maxParticipants": "Max Participants",
"perSession": "Per session",
"team": "Team",
"teamSubtitle": "Facilitators & observers"
},
"modules": {
"guideTitle": "Discussion Guide",
"topicCount": "{count} topics",
"guideDescription": "{minutes} min planned",
"untitledTopic": "Untitled topic",
"moreTopics": "+{count} more",
"guideEmpty": "No topics yet. Add your first topic in the guide editor.",
"manageGuide": "Manage guide",
"configTitle": "Session Configuration",
"maxParticipantsLabel": "Max participants per session",
"waitingRoom": "Waiting room enabled",
"consent": "Consent required",
"backroom": "Observers hidden from participants",
"configure": "Configure",
"liveSessionTitle": "Live Session",
"liveSessionComingSoon": "Moderated live discussion is coming soon.",
"reportsTitle": "Results & Reports",
"reportsComingSoon": "Session results and analysis will appear here."
}
},
"studyCreation": {
Expand Down
33 changes: 33 additions & 0 deletions src/app/plugins/locales/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -2064,6 +2064,39 @@
"addPrompt": "Agregar pregunta",
"removePrompt": "Eliminar pregunta",
"duration": "Minutos"
},
"dashboard": {
"typeLabel": "Grupo Focal",
"subtitle": "Gestiona tu guía de discusión, participantes y sesiones moderadas desde un solo panel."
},
"studyOverview": {
"topics": "Temas de Discusión",
"topicsSubtitle": "En la guía",
"totalDuration": "Duración Total",
"durationSubtitle": "Planificada",
"maxParticipants": "Máx. Participantes",
"perSession": "Por sesión",
"team": "Equipo",
"teamSubtitle": "Facilitadores y observadores"
},
"modules": {
"guideTitle": "Guía de Discusión",
"topicCount": "{count} temas",
"guideDescription": "{minutes} min planificados",
"untitledTopic": "Tema sin título",
"moreTopics": "+{count} más",
"guideEmpty": "Aún no hay temas. Agrega tu primer tema en el editor de la guía.",
"manageGuide": "Gestionar guía",
"configTitle": "Configuración de la Sesión",
"maxParticipantsLabel": "Máx. participantes por sesión",
"waitingRoom": "Sala de espera activada",
"consent": "Consentimiento requerido",
"backroom": "Observadores ocultos a los participantes",
"configure": "Configurar",
"liveSessionTitle": "Sesión en Vivo",
"liveSessionComingSoon": "La discusión moderada en vivo estará disponible pronto.",
"reportsTitle": "Resultados e Informes",
"reportsComingSoon": "Los resultados y el análisis de la sesión aparecerán aquí."
}
},
"studyCreation": {
Expand Down
6 changes: 6 additions & 0 deletions src/shared/utils/statusUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export const getStatusColor = (status) => {
// Success states
active: 'success',
completed: 'success',
finished: 'success',
success: 'success',
pass: 'success',
accepted: 'success',
Expand All @@ -43,6 +44,7 @@ export const getStatusColor = (status) => {
// Info states
info: 'info',
draft: 'info',
upcoming: 'info',
}

return statusMap[statusStr] || 'grey'
Expand All @@ -65,6 +67,7 @@ export const getStatusIcon = (status) => {
// Success states
active: 'mdi-play-circle',
completed: 'mdi-check-circle',
finished: 'mdi-check-circle',
success: 'mdi-check-circle',
pass: 'mdi-check-circle',
accepted: 'mdi-check-circle',
Expand All @@ -88,6 +91,7 @@ export const getStatusIcon = (status) => {
// Info states
info: 'mdi-information',
draft: 'mdi-file-document-outline',
upcoming: 'mdi-calendar-clock',
}

return iconMap[statusStr] || 'mdi-help-circle'
Expand All @@ -109,6 +113,8 @@ export const getStatusText = (status) => {
const textMap = {
active: 'Active',
completed: 'Completed',
finished: 'Finished',
upcoming: 'Upcoming',
success: 'Success',
pass: 'Pass',
accepted: 'Accepted',
Expand Down
75 changes: 75 additions & 0 deletions src/ux/FocusGroup/components/manager/StudyOverview.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
<template>
<v-row>
<v-col cols="12" md="6" class="py-0">
<ManagerMetricCard
:title="t('focusGroup.studyOverview.topics')"
:value="topicCount"
:subtitle="t('focusGroup.studyOverview.topicsSubtitle')"
icon="mdi-format-list-numbered"
/>
</v-col>

<v-col cols="12" md="6" class="py-0">
<ManagerMetricCard
:title="t('focusGroup.studyOverview.totalDuration')"
:value="t('manager.studyOverview.minUnit', { value: totalDuration })"
:subtitle="t('focusGroup.studyOverview.durationSubtitle')"
icon="mdi-timer-outline"
/>
</v-col>

<v-col cols="12" md="6" class="py-0">
<ManagerMetricCard
:title="t('focusGroup.studyOverview.maxParticipants')"
:value="maxParticipants"
:subtitle="t('focusGroup.studyOverview.perSession')"
icon="mdi-account-group"
/>
</v-col>

<v-col cols="12" md="6" class="py-0">
<ManagerMetricCard
:title="t('focusGroup.studyOverview.team')"
:value="teamSize"
:subtitle="t('focusGroup.studyOverview.teamSubtitle')"
icon="mdi-account-multiple-outline"
/>
</v-col>
</v-row>
</template>

<script setup>
import { computed } from 'vue'
import { useI18n } from 'vue-i18n'
import ManagerMetricCard from '@/shared/components/manager/ManagerMetricCard.vue'

const { t } = useI18n()

const props = defineProps({
test: {
type: Object,
default: () => ({}),
},
})

const discussionGuide = computed(() =>
Array.isArray(props.test?.discussionGuide) ? props.test.discussionGuide : [],
)

const topicCount = computed(() => discussionGuide.value.length)

const totalDuration = computed(() =>
discussionGuide.value.reduce(
(total, topic) => total + (topic?.durationMinutes || 0),
0,
),
)

const maxParticipants = computed(() => props.test?.config?.maxParticipants ?? '—')

const teamSize = computed(() => {
const cooperators = props.test?.cooperators
if (!Array.isArray(cooperators)) return 0
return cooperators.filter((cooperator) => cooperator.accepted === true).length
})
</script>
Loading
Loading