5673-claim-development & crudModel #71

Merged
alexm merged 33 commits from 5673-claim-development into dev 2023-09-28 07:46:02 +00:00
10 changed files with 541 additions and 293 deletions
Showing only changes of commit c139e8034b - Show all commits

View File

@ -0,0 +1,339 @@
<script setup>
import axios from 'axios';
import { onMounted, onUnmounted, computed, ref, watch } from 'vue';
import { useI18n } from 'vue-i18n';
import { useQuasar } from 'quasar';
import { useState } from 'src/composables/useState';
import { useValidator } from 'src/composables/useValidator';
import { useStateStore } from 'stores/useStateStore';
import VnPaginate from 'components/ui/VnPaginate.vue';
import VnConfirm from 'components/ui/VnConfirm.vue';
import SkeletonTable from 'components/ui/SkeletonTable.vue';
const quasar = useQuasar();
const state = useState();
const stateStore = useStateStore();
const { t } = useI18n();
const { validate } = useValidator();
const $props = defineProps({
model: {
type: String,
default: '',
},
url: {
type: String,
default: '',
},
saveUrl: {
type: String,
default: null,
},
primaryKey: {
type: String,
default: 'id',
},
dataRequired: {
type: Object,
default: null,
},
defaultSave: {
type: Boolean,
default: true,
},
defaultReset: {
type: Boolean,
default: true,
},
defaultRemove: {
type: Boolean,
default: true,
},
selected: {
type: Object,
default: null,
},
});
const isLoading = ref(false);
const hasChanges = ref(false);
const originalData = ref();
const vnPaginateRef = ref();
const formData = computed(() => state.get($props.model));
const formUrl = computed(() => $props.url);
const emit = defineEmits(['onFetch', 'update:selected']);
defineExpose({
insert,
remove,
onSubmit,
reset,
hasChanges,
});
onMounted(async () => {
await fetch();
});
onUnmounted(() => {
state.unset($props.model);
});
function tMobile(...args) {
if (!quasar.platform.is.mobile) return t(...args);
}
async function fetch(data) {
if (data && Array.isArray(data)) {
let $index = 0;
data.map((d) => (d.$index = $index++));
}
state.set($props.model, data);
originalData.value = data && JSON.parse(JSON.stringify(data));
watch(formData.value, () => (hasChanges.value = true));
emit('onFetch', state.get($props.model));
}
function reset() {
state.set($props.model, originalData.value);
watch(formData.value, () => (hasChanges.value = true));
hasChanges.value = false;
}
// eslint-disable-next-line vue/no-dupe-keys
function filter(value, update, filterOptions) {
update(
() => {
const { options, filterFn, field } = filterOptions;
options.value = filterFn(options, value, field);
},
(ref) => {
ref.setOptionIndex(-1);
ref.moveOptionSelection(1, true);
}
);
}
async function onSubmit() {
if (!hasChanges.value) {
return quasar.notify({
type: 'negative',
message: t('globals.noChanges'),
});
}
isLoading.value = true;
await saveChanges();
}
async function saveChanges(data) {
const changes = data || getChanges();
try {
await axios.post($props.saveUrl || $props.url + '/crud', changes);
} catch (e) {
return (isLoading.value = false);
}
originalData.value = JSON.parse(JSON.stringify(formData.value));
hasChanges.value = false;
isLoading.value = false;
if (changes.creates?.length) await vnPaginateRef.value.fetch();
}
async function insert() {
const $index = formData.value.length
? formData.value[formData.value.length - 1].$index + 1
: 0;
formData.value.push(Object.assign({ $index }, $props.dataRequired));
hasChanges.value = true;
}
alexm marked this conversation as resolved
Review

Esto lo dejo asi por si en un futuro se quiere hacer que puedas borrar una linea en especifico (como esta en salix que al final de la linea esta el boton de borrar) Pero teniendo los checkbox de momento no lo veo necesario

Esto lo dejo asi por si en un futuro se quiere hacer que puedas borrar una linea en especifico (como esta en salix que al final de la linea esta el boton de borrar) Pero teniendo los checkbox de momento no lo veo necesario
// function addRemove(ids) {
// for (let id of ids) {
// const index = removed.value.indexOf(id);
// if (index > -1) {
// removed.value = removed.value.slice(index, 1);
// continue;
// }
// removed.value.push(id);
// }
// }
async function remove(data) {
if (!data.length)
return quasar.notify({
type: 'warning',
message: t('globals.noChanges'),
});
const pk = $props.primaryKey;
let ids = data.map((d) => d[pk]).filter(Boolean);
let preRemove = data.map((d) => (d[pk] ? null : d.$index)).filter(Boolean);
let newData = formData.value;
// addRemove(ids);
if (preRemove.length) {
newData = newData.filter(
(form) => !preRemove.some((index) => index == form.$index)
);
state.set($props.model, newData);
const changes = getChanges();
if (!changes.creates?.length && !changes.updates?.length)
hasChanges.value = false;
}
if (ids.length) {
quasar
.dialog({
component: VnConfirm,
componentProps: {
title: t('confirmDeletion'),
message: t('confirmDeletionMessage'),
newData,
ids,
},
})
.onOk(async () => {
await saveChanges({ deletes: ids });
newData = newData.filter((form) => !ids.some((id) => id == form[pk]));
state.set($props.model, newData);
});
}
emit('update:selected', []);
}
watch(formUrl, async () => {
originalData.value = null;
reset();
fetch();
});
function getChanges() {
const updates = [];
const creates = [];
const pk = $props.primaryKey;
for (const [i, row] of formData.value.entries()) {
if (!row[pk]) {
creates.push(row);
} else if (originalData.value) {
const data = getDifferences(originalData.value[i], row);
if (!isEmpty(data)) {
updates.push({
data,
where: { [pk]: row[pk] },
});
}
}
}
const changes = { updates, creates };
for (let prop in changes) {
if (changes[prop].length === 0) changes[prop] = undefined;
}
return changes;
}
function getDifferences(obj1, obj2) {
let diff = {};
for (let key in obj1) {
if (obj2[key] && obj1[key] !== obj2[key]) {
diff[key] = obj2[key];
}
}
for (let key in obj2) {
if (obj1[key] === undefined && obj2[key]) {
diff[key] = obj2[key];
}
}
return diff;
}
function isEmpty(obj) {
if (obj == null) return true;
if (obj === undefined) return true;
if (Object.keys(obj).length === 0) return true;
if (obj.length > 0) return false;
}
</script>
<template>
<QBanner v-if="hasChanges" class="text-white bg-warning">
<QIcon name="warning" size="md" class="q-mr-md" />
<span>{{ t('globals.changesToSave') }}</span>
</QBanner>
<VnPaginate
@submit="onSubmit"
@reset="reset"
:url="url"
v-bind="$attrs"
@on-fetch="fetch"
class="q-pa-md"
:skeleton="false"
ref="vnPaginateRef"
>
<template #body v-if="formData">
<slot
name="body"
:rows="formData"
:validate="validate"
:filter="filter"
></slot>
</template>
</VnPaginate>
<SkeletonTable v-if="!formData" />
<Teleport to="#st-actions" v-if="stateStore.isSubToolbarShown()">
<QBtnGroup push class="q-gutter-x-sm">
<slot name="moreActions" />
<QBtn
:label="tMobile('globals.remove')"
color="primary"
icon="delete"
@click="remove(selected)"
:disable="!selected?.length"
:title="t('globals.remove')"
v-if="$props.defaultRemove"
/>
<QBtn
:label="tMobile('globals.reset')"
color="primary"
icon="restart_alt"
flat
@click="reset"
:disable="!hasChanges"
:title="t('globals.reset')"
v-if="$props.defaultReset"
/>
<QBtn
:label="tMobile('globals.save')"
color="primary"
icon="save"
@click="onSubmit"
:disable="!hasChanges"
:title="t('globals.save')"
v-if="$props.defaultSave"
/>
</QBtnGroup>
</Teleport>
<QInnerLoading
:showing="isLoading"
:label="t('globals.pleaseWait')"
color="primary"
/>
</template>
<i18n>
{
"en": {
"confirmDeletion": "Confirm deletion",
"confirmDeletionMessage": "Are you sure you want to delete this?"
},
"es": {
"confirmDeletion": "Confirmar eliminación",
"confirmDeletionMessage": "Seguro que quieres eliminar?"
}
}
</i18n>

View File

@ -4,12 +4,14 @@ import { onMounted, onUnmounted, computed, ref, watch } from 'vue';
import { useI18n } from 'vue-i18n';
import { useQuasar } from 'quasar';
import { useState } from 'src/composables/useState';
import { useStateStore } from 'stores/useStateStore';
import { useValidator } from 'src/composables/useValidator';
import SkeletonForm from 'components/ui/SkeletonForm.vue';
const quasar = useQuasar();
const { t } = useI18n();
const state = useState();
const stateStore = useStateStore();
const { t } = useI18n();
const { validate } = useValidator();
const $props = defineProps({
@ -29,63 +31,41 @@ const $props = defineProps({
type: String,
default: null,
},
crud: {
type: Boolean,
default: null,
},
primaryKey: {
type: String,
default: 'id',
},
dataRequired: {
type: Object,
default: null,
},
defaultActions: {
type: Boolean,
default: true,
},
});
const isLoading = ref(false);
const hasChanges = ref(false);
const formData = computed(() => state.get($props.model));
const originalData = ref();
const formUrl = computed(() => $props.url);
const stActionsExist = ref(false);
const emit = defineEmits(['onFetch']);
defineExpose({
save,
insert,
remove,
onSubmit,
reset,
hasChanges,
});
onMounted(async () => {
await fetch();
stActionsExist.value = !!document.querySelector('#st-actions');
});
onMounted(async () => await fetch());
onUnmounted(() => {
state.unset($props.model);
});
const isLoading = ref(false);
const hasChanges = ref(false);
const originalData = ref();
const formData = computed(() => state.get($props.model));
const formUrl = computed(() => $props.url);
function tMobile(...args) {
if (!quasar.platform.is.mobile) return t(...args);
}
async function fetch() {
const { data } = await axios.get($props.url, {
params: { filter: $props.filter },
});
if (Array.isArray(data)) {
let $index = 0;
data.map((d) => (d.$index = $index++));
}
state.set($props.model, data);
originalData.value = JSON.parse(JSON.stringify(data));
originalData.value = Object.assign({}, data);
watch(formData.value, () => (hasChanges.value = true));
@ -100,29 +80,24 @@ async function save() {
});
}
isLoading.value = true;
try {
await axios.patch($props.urlUpdate || $props.url, formData.value);
} catch {
return (isLoading.value = false);
}
await axios.patch($props.urlUpdate || $props.url, formData.value);
originalData.value = JSON.parse(JSON.stringify(formData.value));
originalData.value = formData.value;
hasChanges.value = false;
isLoading.value = false;
}
function reset() {
state.set($props.model, originalData.value);
watch(formData.value, () => (hasChanges.value = true));
hasChanges.value = false;
}
// eslint-disable-next-line vue/no-dupe-keys
function filter(value, update, filterOptions) {
update(
() => {
const { options, filterFn, field } = filterOptions;
const { options, filterFn } = filterOptions;
options.value = filterFn(options, value, field);
options.value = filterFn(options, value);
},
(ref) => {
ref.setOptionIndex(-1);
@ -131,167 +106,42 @@ function filter(value, update, filterOptions) {
);
}
async function crudSave() {
if (!hasChanges.value) {
return quasar.notify({
type: 'negative',
message: t('globals.noChanges'),
});
}
isLoading.value = true;
await saveChanges();
}
async function saveChanges() {
const changes = getChanges();
try {
await axios.post($props.urlUpdate || $props.url + '/crud', changes);
} catch (e) {
return (isLoading.value = false);
}
originalData.value = JSON.parse(JSON.stringify(formData.value));
hasChanges.value = false;
isLoading.value = false;
if (changes.creates?.length) await fetch();
}
async function insert() {
const $index = formData.value[formData.value.length - 1].$index + 1;
formData.value.push(Object.assign({ $index }, $props.dataRequired));
hasChanges.value = true;
}
// function addRemove(ids) {
// for (let id of ids) {
// const index = removed.value.indexOf(id);
// if (index > -1) {
// removed.value = removed.value.slice(index, 1);
// continue;
// }
// removed.value.push(id);
// }
// }
async function remove(data) {
if (!data.length)
return quasar.notify({
type: 'warning',
message: t('globals.noChanges'),
});
const pk = $props.primaryKey;
let ids = data.map((d) => d[pk]).filter(Boolean);
let preRemove = data.map((d) => d.$index).filter(Boolean);
let newData = formData.value;
// addRemove(ids);
if (preRemove.length) {
newData = newData.filter(
(form) => !preRemove.some((index) => index == form.$index)
);
state.set($props.model, newData);
const changes = getChanges();
if (!changes.creates?.length && !changes.updates?.length)
hasChanges.value = false;
}
if (ids.length) {
await saveChanges({ deletes: ids });
newData = newData.filter((form) => !ids.some((id) => id == form[pk]));
state.set($props.model, newData);
}
}
async function onSubmit() {
if ($props.crud) return crudSave();
return save();
}
watch(formUrl, async () => {
originalData.value = null;
reset();
fetch();
});
function getChanges() {
const updates = [];
const creates = [];
const pk = $props.primaryKey;
for (const [i, row] of formData.value.entries()) {
if (!row[pk]) {
creates.push(row);
} else if (originalData.value) {
const data = getDifferences(originalData.value[i], row);
if (!isEmpty(data)) {
updates.push({
data,
where: { [pk]: row[pk] },
});
}
}
}
const changes = { updates, creates };
for (let prop in changes) {
if (changes[prop].length === 0) changes[prop] = undefined;
}
return changes;
}
function getDifferences(obj1, obj2) {
let diff = {};
for (let key in obj1) {
if (obj2[key] && obj1[key] !== obj2[key]) {
diff[key] = obj2[key];
}
}
for (let key in obj2) {
if (obj1[key] === undefined && obj2[key]) {
diff[key] = obj2[key];
}
}
return diff;
}
function isEmpty(obj) {
if (obj == null) return true;
if (obj === undefined) return true;
if (Object.keys(obj).length === 0) return true;
if (obj.length > 0) return false;
}
</script>
<template>
<QBanner v-if="hasChanges" class="text-white bg-warning">
<QIcon name="warning" size="md" class="q-mr-md" />
<span>{{ t('globals.changesToSave') }}</span>
</QBanner>
<QForm v-if="formData" @submit="onSubmit" @reset="reset" class="q-pa-md">
<QForm v-if="formData" @submit="save" @reset="reset" class="q-pa-md">
<slot name="form" :data="formData" :validate="validate" :filter="filter"></slot>
</QForm>
<Teleport to="#st-actions" v-if="stActionsExist">
<div class="row q-gutter-x-sm">
<slot name="moreActions" />
<div v-if="$props.defaultActions">
<Teleport to="#st-actions" v-if="stateStore.isSubToolbarShown()">
<div v-if="$props.defaultActions">
<QBtnGoup push class="q-gutter-x-sm">
<slot name="moreActions" />
<QBtn
:label="t('globals.save')"
:label="tMobile('globals.reset')"
color="primary"
icon="save"
@click="onSubmit"
:disable="!hasChanges"
/>
<QBtn
:label="t('globals.reset')"
color="primary"
class="q-ml-sm"
icon="restart_alt"
flat
@click="reset"
:disable="!hasChanges"
:title="t('globals.reset')"
/>
</div>
<QBtn
:label="tMobile('globals.save')"
color="primary"
icon="save"
@click="save"
:disable="!hasChanges"
:title="t('globals.save')"
/>
</QBtnGoup>
</div>
Outdated
Review

$props.saveFn que le puedas pasar una función(data)

$props.saveFn que le puedas pasar una función(data)
</Teleport>
<SkeletonForm v-if="!formData" />

View File

@ -0,0 +1,50 @@
<template>
<div class="q-pa-md w">
<div class="row q-gutter-md q-mb-md">
<div class="col-1">
<QSkeleton type="rect" square />
</div>
<div class="col">
<QSkeleton type="rect" square />
</div>
<div class="col">
<QSkeleton type="rect" square />
</div>
<div class="col">
<QSkeleton type="rect" square />
</div>
<div class="col">
<QSkeleton type="rect" square />
</div>
<div class="col">
<QSkeleton type="rect" square />
</div>
</div>
<div class="row q-gutter-md q-mb-md" v-for="n in 5" :key="n">
<div class="col-1">
<QSkeleton type="QInput" square />
</div>
<div class="col">
<QSkeleton type="QInput" square />
</div>
<div class="col">
<QSkeleton type="QInput" square />
</div>
<div class="col">
<QSkeleton type="QInput" square />
</div>
<div class="col">
<QSkeleton type="QInput" square />
</div>
<div class="col">
<QSkeleton type="QInput" square />
</div>
</div>
</div>
</template>
<style lang="scss" scoped>
.w {
width: 80vw;
}
</style>

View File

@ -46,6 +46,10 @@ const props = defineProps({
type: Number,
default: 500,
},
skeleton: {
type: Boolean,
default: true,
},
});
const emit = defineEmits(['onFetch', 'onPaginate']);
@ -144,7 +148,10 @@ async function onLoad(...params) {
{{ t('No results found') }}
</h5>
</div>
<div v-if="props.autoLoad && !store.data" class="card-list q-gutter-y-md">
<div
v-if="props.skeleton && props.autoLoad && !store.data"
class="card-list q-gutter-y-md"
>
<QCard class="card" v-for="$index in $props.limit" :key="$index">
<QItem v-ripple class="q-pa-none items-start cursor-pointer q-hoverable">
<QItemSection class="q-pa-md">

View File

@ -35,4 +35,19 @@ body.body--light {
color: white;
}
}
--vn-text: #000000;
--vn-gray: #dddddd;
--vn-label: #5f5f5f;
--vn-dark: white;
}
body.body--dark {
--vn-text: #ffffff;
--vn-gray: #313131;
--vn-label: #a8a8a8;
--vn-dark: #292929;
}
.bg-vn-dark {
background-color: var(--vn-dark);
}

View File

@ -29,6 +29,7 @@ const claimSections = [
let salixUrl;
onMounted(async () => {
salixUrl = await getUrl(`claim/${entityId.value}`);
stateStore.setSubtoolbar();
});
</script>
<template>
@ -64,10 +65,8 @@ onMounted(async () => {
</QScrollArea>
</QDrawer>
<QPageContainer>
<QToolbar id="sub-toolbar" class="bg-dark text-white justify-end">
<div id="st-data">
{{ route.meta?.title && t(`claim.pageTitles.${route.meta.title}`) }}
</div>
<QToolbar class="bg-vn-dark justify-end">
<div id="st-data"></div>
<QSpace />
<div id="st-actions"></div>
</QToolbar>

View File

@ -1,8 +1,8 @@
<script setup>
import { ref, computed, onMounted } from 'vue';
import { ref, computed } from 'vue';
import { useI18n } from 'vue-i18n';
import { useRoute } from 'vue-router';
import FormModel from 'components/FormModel.vue';
import CrudModel from 'components/CrudModel.vue';
import FetchData from 'components/FetchData.vue';
import VnSelectFilter from 'components/common/VnSelectFilter.vue';
@ -122,27 +122,20 @@ const columns = computed(() => [
/>
<div class="column items-center">
<div class="list">
<FormModel
<CrudModel
data-key="ClaimDevelopments"
url="ClaimDevelopments"
:crud="true"
:filter="developmentsFilter"
model="claimDevelopment"
:filter="developmentsFilter"
ref="claimDevelopmentForm"
:data-required="{ claimFk: route.params.id }"
v-model:selected="selected"
auto-load
>
<template #moreActions>
<QBtn
:label="t('globals.remove')"
color="primary"
icon="delete"
@click="claimDevelopmentForm.remove(selected)"
:disable="!selected.length"
/>
</template>
<template #form="{ data }">
<template #body="{ rows }">
<QTable
:columns="columns"
:rows="data"
:rows="rows"
:pagination="{ rowsPerPage: 0 }"
row-key="$index"
selection="multiple"
@ -187,7 +180,7 @@ const columns = computed(() => [
</template>
</QTable>
</template>
</FormModel>
</CrudModel>
</div>
</div>
<QPageSticky position="bottom-right" :offset="[25, 25]">

View File

@ -6,7 +6,7 @@ import { useQuasar } from 'quasar';
import { useRoute } from 'vue-router';
import { useArrayData } from 'composables/useArrayData';
import { useStateStore } from 'stores/useStateStore';
import VnPaginate from 'components/ui/VnPaginate.vue';
import CrudModel from 'components/CrudModel.vue';
import FetchData from 'components/FetchData.vue';
import VnConfirm from 'components/ui/VnConfirm.vue';
@ -36,6 +36,7 @@ const linesFilter = {
},
};
const claimLinesForm = ref();
const claim = ref(null);
async function onFetchClaim(data) {
claim.value = data;
@ -46,6 +47,7 @@ async function onFetchClaim(data) {
const amount = ref(0);
const amountClaimed = ref(0);
async function onFetch(rows) {
if (!rows || rows.length) return;
amount.value = rows.reduce(
(acumulator, { sale }) => acumulator + sale.price * sale.quantity,
0
@ -141,47 +143,6 @@ function onUpdateDiscount(response) {
});
}
async function confirmRemove() {
const rows = selected.value;
const count = rows.length;
if (count === 0) {
return quasar.notify({
message: 'You must select at least one row',
type: 'warning',
});
}
quasar
.dialog({
component: VnConfirm,
componentProps: {
title: t('Delete claimed sales'),
message: t('You are about to remove {count} rows', count, { count }),
data: { rows },
promise: remove,
},
})
.onOk(() => {
for (const row of rows) {
const orgData = store.data;
const index = orgData.findIndex((item) => item.id === row.id);
store.data.splice(index, 1);
selected.value = [];
}
});
}
async function remove({ rows }) {
if (!rows.length) return;
const body = { deletes: rows.map((row) => row.id) };
await axios.post(`ClaimBeginnings/crud`, body);
quasar.notify({
type: 'positive',
message: t('globals.rowRemoved'),
});
}
function showImportDialog() {
quasar
.dialog({
@ -191,10 +152,8 @@ function showImportDialog() {
}
</script>
<template>
<QPageSticky position="top" :offset="[0, 0]" expand>
<Teleport to="#st-data" v-if="stateStore.isSubToolbarShown()">
<QToolbar class="bg-dark text-white">
<QToolbarTitle> {{ t('Claimed lines') }} </QToolbarTitle>
<QSpace />
<div class="row q-gutter-md">
<div>
{{ t('Amount') }}
@ -211,7 +170,7 @@ function showImportDialog() {
</div>
</div>
</QToolbar>
</QPageSticky>
</Teleport>
<FetchData
:url="`Claims/${route.params.id}`"
@ -221,11 +180,16 @@ function showImportDialog() {
/>
<div class="column items-center">
<div class="list">
<VnPaginate
<CrudModel
data-key="ClaimLines"
ref="claimLinesForm"
:url="`Claims/${route.params.id}/lines`"
save-url="ClaimBeginnings/crud"
:filter="linesFilter"
@on-fetch="onFetch"
v-model:selected="selected"
:default-save="false"
:default-reset="false"
auto-load
>
<template #body="{ rows }">
@ -361,46 +325,12 @@ function showImportDialog() {
</template>
</QTable>
</template>
</VnPaginate>
</CrudModel>
</div>
</div>
<Teleport
v-if="stateStore.isHeaderMounted() && !$q.screen.lt.sm"
to="#actions-prepend"
>
<div class="row q-gutter-x-sm">
<QBtn
v-if="selected.length > 0"
@click="confirmRemove"
icon="delete"
color="primary"
flat
dense
rounded
>
<QTooltip bottom> {{ t('globals.remove') }} </QTooltip>
</QBtn>
<QBtn @click="showImportDialog" icon="add" color="primary" flat dense rounded>
<QTooltip bottom> {{ t('globals.add') }} </QTooltip>
</QBtn>
<QSeparator vertical />
</div>
</Teleport>
<!-- v-if="quasar.platform.is.mobile" -->
<QPageSticky v-if="$q.screen.lt.sm" position="bottom" :offset="[0, 0]" expand>
<QToolbar class="bg-primary text-white q-pa-none">
<QTabs class="full-width" align="justify" inline-label narrow-indicator>
<QTab @click="showImportDialog" icon="add" :label="t('globals.add')" />
<QSeparator vertical inset />
<QTab
@click="confirmRemove"
icon="delete"
:label="t('globals.remove')"
:disable="selected.length === 0"
/>
</QTabs>
</QToolbar>
<QPageSticky position="bottom-right" :offset="[25, 25]">
<QBtn fab color="primary" icon="add" @click="showImportDialog()" />
</QPageSticky>
</template>
@ -421,7 +351,6 @@ en:
You are about to remove <strong>{count}</strong> row |
You are about to remove <strong>{count}</strong> rows'
es:
Claimed lines: Líneas reclamadas
Delivered: Entregado
Quantity: Cantidad
Claimed: Reclamada

View File

@ -5,6 +5,7 @@ export const useStateStore = defineStore('stateStore', () => {
const isMounted = ref(false);
const leftDrawer = ref(false);
const rightDrawer = ref(false);
const subToolbar = ref(false);
function toggleLeftDrawer() {
leftDrawer.value = !leftDrawer.value;
@ -18,6 +19,10 @@ export const useStateStore = defineStore('stateStore', () => {
isMounted.value = true;
}
function setSubtoolbar() {
subToolbar.value = true;
}
function isHeaderMounted() {
return isMounted.value;
}
@ -30,6 +35,10 @@ export const useStateStore = defineStore('stateStore', () => {
return rightDrawer.value;
}
function isSubToolbarShown() {
return subToolbar.value;
}
return {
leftDrawer,
rightDrawer,
@ -39,5 +48,7 @@ export const useStateStore = defineStore('stateStore', () => {
toggleRightDrawer,
isLeftDrawerShown,
isRightDrawerShown,
setSubtoolbar,
isSubToolbarShown,
};
});

View File

@ -0,0 +1,55 @@
/// <reference types="cypress" />
describe('ClaimPhoto', () => {
beforeEach(() => {
const claimId = 1;
cy.login('developer');
cy.visit(`/#/claim/${claimId}/photos`);
});
it('should add new file', () => {
cy.get('label > .q-btn').click();
cy.get('label > .q-btn input').selectFile('test/cypress/fixtures/image.jpg', {
force: true,
});
cy.get('.q-notification__message').should('have.text', 'Data saved');
});
it('should add new file with drag and drop', () => {
cy.get('.container').selectFile('test/cypress/fixtures/image.jpg', {
action: 'drag-drop',
});
cy.get('.q-notification__message').should('have.text', 'Data saved');
});
it('should open first image dialog change to second and close', () => {
cy.get(
':nth-child(1) > .q-card > .q-img > .q-img__container > .q-img__image'
).click();
cy.get('.q-carousel__slide > .q-img > .q-img__container > .q-img__image').should(
'be.visible'
);
cy.get('.q-carousel__control > .q-btn > .q-btn__content > .q-icon').click();
cy.get(
'.q-dialog__inner > .q-toolbar > .q-btn > .q-btn__content > .q-icon'
).click();
cy.get('.q-carousel__slide > .q-img > .q-img__container > .q-img__image').should(
'not.be.visible'
);
});
it('should remove third and fourth file', () => {
cy.get(
'.multimediaParent > :nth-child(3) > .q-btn > .q-btn__content > .q-icon'
).click();
cy.get('.q-btn--unelevated > .q-btn__content > .block').click();
cy.get('.q-notification__message').should('have.text', 'Data deleted');
cy.get(
'.multimediaParent > :nth-child(3) > .q-btn > .q-btn__content > .q-icon'
).click();
cy.get('.q-btn--unelevated > .q-btn__content > .block').click();
cy.get('.q-notification__message').should('have.text', 'Data deleted');
});
});