feat: 07 => implement status toggle functionality in AgenciesDialog and MainPage components

This commit is contained in:
puriphatt 2025-02-10 11:34:36 +07:00
parent f18d34b02d
commit 4994792597
3 changed files with 97 additions and 7 deletions

View file

@ -199,16 +199,23 @@ watch(
<ProfileBanner <ProfileBanner
prefix="dialog" prefix="dialog"
active active
use-toggle
hide-fade hide-fade
hide-active :toggle-title="$t('status.title')"
:icon="'ph-building-office'" :icon="'ph-building-office'"
:img="imageState.imageUrl || null" :img="imageState.imageUrl || null"
:title="data.name" :title="data.name"
:caption="data.code" :caption="data.code"
:color="`hsla(var(--green-8-hsl)/1)`" :color="`hsla(var(--green-8-hsl)/1)`"
:bg-color="`hsla(var(--green-8-hsl)/0.1)`" :bg-color="`hsla(var(--green-8-hsl)/0.1)`"
v-model:toggle-status="data.status"
@view="viewImage" @view="viewImage"
@edit="editImage" @edit="editImage"
@update:toggle-status="
() => {
data.status = data.status === 'CREATED' ? 'INACTIVE' : 'CREATED';
}
"
/> />
</div> </div>
@ -317,9 +324,10 @@ watch(
> >
<ProfileBanner <ProfileBanner
:prefix="data.name" :prefix="data.name"
active
hide-fade hide-fade
hide-active use-toggle
:active="data.status !== 'INACTIVE'"
:toggle-title="$t('status.title')"
:icon="'ph-building-office'" :icon="'ph-building-office'"
:title="data.name" :title="data.name"
:caption="data.code" :caption="data.code"
@ -330,8 +338,10 @@ watch(
imageState.refreshImageState ? `?ts=${Date.now()}` : '', imageState.refreshImageState ? `?ts=${Date.now()}` : '',
) || null ) || null
" "
v-model:toggle-status="data.status"
@view="viewImage" @view="viewImage"
@edit="editImage" @edit="editImage"
@update:toggle-status="$emit('changeStatus')"
/> />
</div> </div>
@ -354,7 +364,10 @@ watch(
}" }"
style="position: absolute; z-index: 999; top: 0; right: 0" style="position: absolute; z-index: 999; top: 0; right: 0"
> >
<div v-if="true" class="surface-1 row rounded"> <div
v-if="data.status !== 'INACTIVE'"
class="surface-1 row rounded"
>
<UndoButton <UndoButton
v-if="isEdit" v-if="isEdit"
id="btn-info-basic-undo" id="btn-info-basic-undo"

View file

@ -97,6 +97,7 @@ const blankFormData: InstitutionPayload = {
districtId: '', districtId: '',
provinceId: '', provinceId: '',
selectedImage: '', selectedImage: '',
status: 'CREATED',
}; };
const refAgenciesDialog = ref(); const refAgenciesDialog = ref();
@ -155,6 +156,7 @@ function assignFormData(data: Institution) {
districtId: data.districtId, districtId: data.districtId,
provinceId: data.provinceId, provinceId: data.provinceId,
selectedImage: data.selectedImage, selectedImage: data.selectedImage,
status: data.status,
}; };
} }
@ -175,6 +177,7 @@ async function submit(opt?: { selectedImage: string }) {
subDistrictId: formData.value.subDistrictId, subDistrictId: formData.value.subDistrictId,
districtId: formData.value.districtId, districtId: formData.value.districtId,
provinceId: formData.value.provinceId, provinceId: formData.value.provinceId,
status: formData.value.status,
}; };
if ( if (
(pageState.isDrawerEdit && currAgenciesData.value?.id) || (pageState.isDrawerEdit && currAgenciesData.value?.id) ||
@ -250,6 +253,54 @@ async function fetchData(mobileFetch?: boolean) {
} }
} }
async function triggerChangeStatus(data?: Institution) {
const targetId = (data && data.id) || currAgenciesData.value?.id;
const targetStatus = (data && data.status) || currAgenciesData.value?.status;
if (data) assignFormData(data);
if (targetId === undefined || targetStatus === undefined) return;
return await new Promise((resolve, reject) => {
dialog({
color: targetStatus !== 'INACTIVE' ? 'warning' : 'info',
icon:
targetStatus !== 'INACTIVE'
? 'mdi-alert'
: 'mdi-message-processing-outline',
title: t('dialog.title.confirmChangeStatus'),
actionText:
targetStatus !== 'INACTIVE' ? t('general.close') : t('general.open'),
message:
targetStatus !== 'INACTIVE'
? t('dialog.message.confirmChangeStatusOff')
: t('dialog.message.confirmChangeStatusOn'),
action: async () => {
await changeStatus(targetId).then(resolve).catch(reject);
},
cancel: () => {},
});
});
}
async function changeStatus(id?: string) {
const targetId = id || currAgenciesData.value?.id;
if (targetId === undefined) return;
formData.value.status =
formData.value.status !== 'INACTIVE' ? 'INACTIVE' : 'ACTIVE';
const res = await institutionStore.editInstitution({
id: targetId,
...formData.value,
});
if (res) {
formData.value.status = res.status;
if (currAgenciesData.value) {
currAgenciesData.value.status = res.status;
}
await fetchData();
}
}
onMounted(async () => { onMounted(async () => {
navigatorStore.current.title = 'agencies.title'; navigatorStore.current.title = 'agencies.title';
navigatorStore.current.path = [{ text: 'agencies.caption', i18n: true }]; navigatorStore.current.path = [{ text: 'agencies.caption', i18n: true }];
@ -540,6 +591,18 @@ watch(
</div> </div>
</template> </template>
</q-img> </q-img>
<q-badge
class="absolute-bottom-right no-padding"
style="
border-radius: 50%;
min-width: 8px;
min-height: 8px;
"
:style="{
background: `var(--${props.row.status === 'INACTIVE' ? 'stone-5' : 'green-6'})`,
}"
></q-badge>
</q-avatar> </q-avatar>
<span class="col q-pl-md"> <span class="col q-pl-md">
<div> <div>
@ -606,7 +669,6 @@ watch(
" "
/> />
<KebabAction <KebabAction
hide-toggle
:id-name="props.row.id" :id-name="props.row.id"
:status="props.row.status" :status="props.row.status"
@view=" @view="
@ -622,6 +684,7 @@ watch(
} }
" "
@delete="() => triggerDelete(props.row.id)" @delete="() => triggerDelete(props.row.id)"
@change-status="() => triggerChangeStatus(props.row)"
/> />
</q-td> </q-td>
</q-tr> </q-tr>
@ -649,6 +712,18 @@ watch(
</div> </div>
</template> </template>
</q-img> </q-img>
<q-badge
class="absolute-bottom-right no-padding"
style="
border-radius: 50%;
min-width: 10px;
min-height: 10px;
"
:style="{
background: `var(--${props.row.status === 'INACTIVE' ? 'stone-5' : 'green-6'})`,
}"
></q-badge>
</q-avatar> </q-avatar>
<span class="text-weight-bold column q-pl-md"> <span class="text-weight-bold column q-pl-md">
{{ {{
@ -677,7 +752,6 @@ watch(
" "
/> />
<KebabAction <KebabAction
hide-toggle
:id-name="props.row.id" :id-name="props.row.id"
:status="props.row.status" :status="props.row.status"
@view=" @view="
@ -693,6 +767,7 @@ watch(
} }
" "
@delete="() => triggerDelete(props.row.id)" @delete="() => triggerDelete(props.row.id)"
@change-status="() => triggerChangeStatus(props.row)"
/> />
</nav> </nav>
</header> </header>
@ -814,6 +889,7 @@ watch(
if (v) await submit({ selectedImage: v }); if (v) await submit({ selectedImage: v });
} }
" "
@change-status="triggerChangeStatus"
:readonly="!pageState.isDrawerEdit" :readonly="!pageState.isDrawerEdit"
:isEdit="pageState.isDrawerEdit" :isEdit="pageState.isDrawerEdit"
v-model="pageState.addModal" v-model="pageState.addModal"

View file

@ -40,7 +40,7 @@ export const useInstitution = defineStore('institution-store', () => {
params, params,
}, },
) )
: await api.get<PaginationResult<Institution>>(`/institution`, { : await api.get<PaginationResult<Institution>>('/institution', {
params, params,
}); });
@ -80,6 +80,7 @@ export const useInstitution = defineStore('institution-store', () => {
const res = await api.put(`/institution/${data.id}`, { const res = await api.put(`/institution/${data.id}`, {
...data, ...data,
id: undefined, id: undefined,
group: undefined,
}); });
if (res.status < 400) { if (res.status < 400) {
return res.data; return res.data;