|
|
@@ -90,6 +90,59 @@
|
|
|
{{ $t("associado.first_access_password_hint") }}
|
|
|
</div>
|
|
|
</q-card-section>
|
|
|
+
|
|
|
+ <q-card-section v-if="associado" class="q-pt-none">
|
|
|
+ <div class="text-h6 q-mb-sm">{{ $t("associado.dependents") }}</div>
|
|
|
+
|
|
|
+ <q-list v-if="dependents.length > 0" class="column q-mb-md">
|
|
|
+ <div
|
|
|
+ v-for="dep in dependents"
|
|
|
+ :key="dep.id"
|
|
|
+ class="dependent-row row items-center no-wrap q-my-sm"
|
|
|
+ >
|
|
|
+ <q-avatar size="40px" class="dependent-avatar q-mr-md" text-color="white">
|
|
|
+ {{ initials(dep.name) }}
|
|
|
+ </q-avatar>
|
|
|
+
|
|
|
+ <div class="col column">
|
|
|
+ <span class="dependent-name">{{ dep.name }}</span>
|
|
|
+ <span class="dependent-kinship">
|
|
|
+ {{ $t(`associado.kinship_options.${dep.kinship}`) }}
|
|
|
+ </span>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <q-badge
|
|
|
+ :color="dependentStatusColor(dep.status)"
|
|
|
+ class="q-mr-sm text-capitalize"
|
|
|
+ style="font-size:11px; padding: 3px 8px; border-radius: 20px;"
|
|
|
+ >
|
|
|
+ {{ dependentStatusLabel(dep.status) }}
|
|
|
+ </q-badge>
|
|
|
+
|
|
|
+ <q-btn
|
|
|
+ flat
|
|
|
+ round
|
|
|
+ dense
|
|
|
+ icon="mdi-pencil"
|
|
|
+ color="violet-normal"
|
|
|
+ @click="onEditDependent(dep)"
|
|
|
+ />
|
|
|
+ <q-btn
|
|
|
+ flat
|
|
|
+ round
|
|
|
+ dense
|
|
|
+ icon="mdi-trash-can-outline"
|
|
|
+ color="negative"
|
|
|
+ @click="onDeleteDependent(dep)"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ </q-list>
|
|
|
+
|
|
|
+ <div v-else class="text-center q-py-md text-grey">
|
|
|
+ {{ $t("associado.no_dependents") }}
|
|
|
+ </div>
|
|
|
+ </q-card-section>
|
|
|
+
|
|
|
<q-card-actions>
|
|
|
<q-space />
|
|
|
<q-btn
|
|
|
@@ -112,13 +165,15 @@
|
|
|
</template>
|
|
|
|
|
|
<script setup>
|
|
|
-import { ref, computed, useTemplateRef, watch } from "vue";
|
|
|
+import { ref, computed, useTemplateRef, watch, onMounted, defineAsyncComponent } from "vue";
|
|
|
import { useInputRules } from "src/composables/useInputRules";
|
|
|
-import { useDialogPluginComponent } from "quasar";
|
|
|
+import { useDialogPluginComponent, useQuasar } from "quasar";
|
|
|
import { useI18n } from "vue-i18n";
|
|
|
import { createUser, updateUser } from "src/api/user";
|
|
|
+import { getDependentsByUser, deleteDependent } from "src/api/profile";
|
|
|
import { useFormUpdateTracker } from "src/composables/useFormUpdateTracker";
|
|
|
import { useSubmitHandler } from "src/composables/useSubmitHandler";
|
|
|
+import { useDependentStatus } from "src/composables/useDependentStatus";
|
|
|
|
|
|
import DefaultDialogHeader from "src/components/defaults/DefaultDialogHeader.vue";
|
|
|
import DefaultInput from "src/components/defaults/DefaultInput.vue";
|
|
|
@@ -128,6 +183,10 @@ import DefaultSelect from "src/components/defaults/DefaultSelect.vue";
|
|
|
import PositionSelect from "src/components/selects/PositionSelect.vue";
|
|
|
import SectorSelect from "src/components/selects/SectorSelect.vue";
|
|
|
|
|
|
+const AddEditDependentDialog = defineAsyncComponent(
|
|
|
+ () => import("src/pages/associado/profile/components/AddEditDependentDialog.vue"),
|
|
|
+);
|
|
|
+
|
|
|
defineEmits([...useDialogPluginComponent.emits]);
|
|
|
|
|
|
const { associado, title } = defineProps({
|
|
|
@@ -142,10 +201,54 @@ const { associado, title } = defineProps({
|
|
|
});
|
|
|
|
|
|
const { t } = useI18n();
|
|
|
+const $q = useQuasar();
|
|
|
const { inputRules } = useInputRules();
|
|
|
const { dialogRef, onDialogHide, onDialogOK, onDialogCancel } = useDialogPluginComponent();
|
|
|
+const { dependentStatusColor, dependentStatusLabel } = useDependentStatus();
|
|
|
const formRef = useTemplateRef("formRef");
|
|
|
const confirmPassword = ref("");
|
|
|
+const dependents = ref([]);
|
|
|
+
|
|
|
+const initials = (name) => {
|
|
|
+ if (!name) return "?";
|
|
|
+ return name.split(" ").slice(0, 2).map((w) => w[0]).join("").toUpperCase();
|
|
|
+};
|
|
|
+
|
|
|
+const loadDependents = async () => {
|
|
|
+ if (!associado?.id) return;
|
|
|
+ try {
|
|
|
+ dependents.value = await getDependentsByUser(associado.id);
|
|
|
+ } catch {
|
|
|
+ dependents.value = [];
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+onMounted(loadDependents);
|
|
|
+
|
|
|
+const onEditDependent = (dep) => {
|
|
|
+ $q.dialog({
|
|
|
+ component: AddEditDependentDialog,
|
|
|
+ componentProps: {
|
|
|
+ dependent: dep,
|
|
|
+ userId: associado.id,
|
|
|
+ showStatus: true,
|
|
|
+ title: () => t("common.actions.edit") + " " + t("associado.dependent"),
|
|
|
+ },
|
|
|
+ }).onOk(() => loadDependents());
|
|
|
+};
|
|
|
+
|
|
|
+const onDeleteDependent = (dep) => {
|
|
|
+ $q.dialog({
|
|
|
+ title: t("common.actions.delete"),
|
|
|
+ message: t("associado.dependent_delete_confirm", { name: dep.name }),
|
|
|
+ cancel: { flat: true, label: t("common.actions.cancel"), color: "grey-7" },
|
|
|
+ ok: { unelevated: true, label: t("common.actions.delete"), color: "negative" },
|
|
|
+ persistent: true,
|
|
|
+ }).onOk(async () => {
|
|
|
+ await deleteDependent(dep.id);
|
|
|
+ await loadDependents();
|
|
|
+ });
|
|
|
+};
|
|
|
|
|
|
const selectedPosition = ref(
|
|
|
associado?.position ? { label: associado.position.name, value: associado.position.id } : null,
|
|
|
@@ -197,3 +300,33 @@ const onOKClick = async () => {
|
|
|
}
|
|
|
};
|
|
|
</script>
|
|
|
+
|
|
|
+<style lang="scss" scoped>
|
|
|
+@use "src/css/quasar.variables.scss" as *;
|
|
|
+
|
|
|
+.dependent-row {
|
|
|
+ background: $violet-light;
|
|
|
+ border-radius: 8px;
|
|
|
+ padding: 10px 12px;
|
|
|
+}
|
|
|
+
|
|
|
+.dependent-avatar {
|
|
|
+ background: $violet-normal !important;
|
|
|
+ font-size: 14px;
|
|
|
+ font-weight: 700;
|
|
|
+ flex-shrink: 0;
|
|
|
+}
|
|
|
+
|
|
|
+.dependent-name {
|
|
|
+ font-size: 14px;
|
|
|
+ font-weight: 600;
|
|
|
+ color: $color-text;
|
|
|
+ line-height: 1.3;
|
|
|
+}
|
|
|
+
|
|
|
+.dependent-kinship {
|
|
|
+ font-size: 12px;
|
|
|
+ color: $color-text-2;
|
|
|
+ line-height: 1.2;
|
|
|
+}
|
|
|
+</style>
|