#6321 - Negative ticket #158

Open
jsegarra wants to merge 220 commits from 6321_negative_tickets into dev
7 changed files with 206 additions and 50 deletions
Showing only changes of commit 24eaaacb19 - Show all commits

View File

@ -18,8 +18,7 @@ const $props = defineProps({
},
columns: {
type: Number,
required: false,
default: null,
default: 3,
},
});
@ -30,10 +29,7 @@ const tags = computed(() => {
const n = tag.split(`${$props.tag}`)[1];
const key = `${$props.tag}${n}`;
const value = `${$props.value}${n}`;
const val = $props.item[value] ?? '';
const match = $props.item[`match${n}`] ?? '';
const style = match ? 'color:green' : '';
acc[$props.item[key] ?? key] = { val, style, match };
acc[$props.item[key] ?? key] = $props.item[value] ?? '';
return acc;
}, {});
});
@ -51,18 +47,15 @@ const columnStyle = computed(() => {
<template>
<div class="fetchedTags">
<pre>{{ $props.item }}</pre>
<div class="wrap" :style="columnStyle">
<div
v-for="(tag, key) in tags"
v-for="(val, key) in tags"
:key="key"
class="inline-tag"
:title="`${key}: ${tag.val}`"
:class="{ empty: !tag.val }"
:title="`${key}: ${val}`"
:class="{ empty: !val }"
>
<span class="text" :style="tag.style"
>{{ tag.val }}// {{ tag.match }}
</span>
<span class="text">{{ val }} </span>
</div>
</div>
</div>

View File

@ -7,7 +7,8 @@ import { isDialogOpened } from 'src/filters';
const arrayDataStore = useArrayDataStore();
export function useArrayData(key = useRoute().meta.moduleName, userOptions) {
export function useArrayData(key, userOptions) {
key ??= useRoute().meta.moduleName;
if (!key) throw new Error('ArrayData: A key is required to use this composable');
if (!arrayDataStore.get(key)) arrayDataStore.set(key);

View File

@ -12,17 +12,22 @@ import VnInput from 'src/components/common/VnInput.vue';
const MATCH_VALUES = [5, 6, 7, 8];
const { t } = useI18n();
const extractNumericValue = (percentageString) => {
const match = percentageString.match(/(\d+(\.\d+)?)/);
return match ? parseFloat(match[0]) : null;
};
const primaryColor = '#f5b351';
const colorSpacer = '#ecf0f1';
const compatibilityItem = (value) => `${100 * (value / MATCH_VALUES.length)}%`;
const gradientStyle = (value) => {
let color = 'white';
switch (value) {
case value >= 0 && value < 33:
console.error(value, extractNumericValue(compatibilityItem(value)));
const perc = extractNumericValue(compatibilityItem(value));
switch (true) {
case perc >= 0 && perc < 33:
color = 'orange';
break;
case value >= 33 && value < 66:
case perc >= 33 && perc < 66:
color = 'yellow';
break;
@ -62,7 +67,6 @@ const statusConditionalValue = (row) => {
const total = MATCH_VALUES.reduce((acc, i) => acc + row[`match${i}`], 0);
return total;
};
const popupProxyRef = ref(null);
const proposalTableRef = ref(null);
const emit = defineEmits(['onDialogClosed', 'itemReplaced']);
@ -146,6 +150,22 @@ const columns = computed(() => [
name: 'located',
field: 'located',
},
{
name: 'tableActions',
align: 'left',
actions: [
{
title: t('Open details'),
jgallego marked this conversation as resolved Outdated

Aqui no veo correcto usar las variables de colores definidos

Aqui no veo correcto usar las variables de colores definidos

yo lo que no veo correcto es usar el amarillo que nos de javascript sin saber cual és, creemos una variable amarillo porque tal vez en el dark o en el light lo queramos hacer amarillo pero no el mismo tono

yo lo que no veo correcto es usar el amarillo que nos de javascript sin saber cual és, creemos una variable amarillo porque tal vez en el dark o en el light lo queramos hacer amarillo pero no el mismo tono

ok, vale, cambio de style por class

ok, vale, cambio de style por class
icon: 'change_circle',
show: (row) => isSelectionAvailable(row),
action: (row) => {
proposalSelected.value = [row];
confirm();
},
isPrimary: true,
},
],
},
]);
async function confirm() {
@ -161,7 +181,7 @@ async function confirm() {
// schema: 'vn',
// params,
// });
proposalTableRef.value.reload();
// proposalTableRef.value.reload();
emit('itemReplaced', {
type: 'refresh',
quantity: quantity.value,
@ -169,7 +189,6 @@ async function confirm() {
...params,
});
proposalSelected.value = [];
popupProxyRef.value.hide();
} catch (error) {
jsegarra marked this conversation as resolved
Review

30 ?

30 ?
Review

Lo habia reemplazado arroba y faltaba esta

Lo habia reemplazado arroba y faltaba esta
console.error(error);
}
@ -223,7 +242,6 @@ const isSelectionAvailable = (itemProposal) => {
:disable-option="{ card: true, table: true }"
:table="{
'row-key': 'id',
selection: 'single',
}"
>
<template #body-selection="props">
@ -244,18 +262,52 @@ const isSelectionAvailable = (itemProposal) => {
</QCheckbox>
</template>
<template #column-longName="{ row }">
<QTd style="min-width: 800px">
<QTd
style="
max-width: 100%;
display: flex;
max-width: 100%;
/* align-items: center; */
/* justify-content: flex-start; */
/* flex: 1 1 100px; */
flex-shrink: 50px;
flex-wrap: nowrap;
"
>
<QTooltip>
{{ row.id }}
</QTooltip>
<!-- <QBtn flat color="blue" dense>{{ }}</QBtn> -->
<span style="font-size: x-small">({{ row.id }})</span
><span class="link">{{ row.longName }}</span>
<ItemDescriptorProxy :id="row.id" />
<div
id="middle"
style="
/* position: absolute; */
float: left;
margin-right: 2px;
flex: 2 0 5px;
"
:style="{
background: gradientStyle(statusConditionalValue(row)),
}"
class="compatibility"
>
<QTooltip>
{{ compatibilityItem(statusConditionalValue(row)) }}
</QTooltip>
<!-- </div> -->
</div>
<div style="flex: 2 0 100%">
<div>
<span style="font-size: x-small">({{ row.id }})</span
><span class="link">{{ row.longName }}</span>
<!-- :style="{
color: gradientStyle(statusConditionalValue(row)),
}" -->
<ItemDescriptorProxy :id="row.id" />
<section id="portraitGrid">
<!-- -->
<!-- <div id="left">
<!-- <section id="portraitGrid"> -->
<!-- -->
<!-- <div id="left">
<VnImg
:id="row.id"
spinner-color="primary"
@ -264,24 +316,23 @@ const isSelectionAvailable = (itemProposal) => {
class="image remove-bg"
/>
</div> -->
<div id="right" style="min-width: 200px">
<div
id="middle"
:style="{
background: gradientStyle(
statusConditionalValue(row)
),
}"
class="compatibility"
>
<QTooltip>
{{ compatibilityItem(statusConditionalValue(row)) }}
</QTooltip>
<!-- </div> -->
</div>
<FetchedTags :item="row" class="q-mb-xs" columns="4" />
<!-- <FetchedTags :item="row" class="q-mb-xs" columns="4" /> -->
</div>
</section>
<div :key="key" class="inline-tag" v-for="(tag, key) in [5]">
<span
class="text"
:style="{
color: row[`match${tag}`]
? 'green'
: 'var(--vn-label-color)',
}"
>
{{ row[`value${tag}`] }}
</span>
</div>
</div>
<!-- </section> -->
</QTd>
</template>
<template #column-available="{ row }">
@ -326,7 +377,6 @@ const isSelectionAvailable = (itemProposal) => {
</template>
<style lang="scss">
.compatibility {
height: 1vh;
width: 100%;
}

View File

@ -3,7 +3,9 @@ import ItemProposal from './ItemProposal.vue';
import VnImg from 'src/components/ui/VnImg.vue';
import FetchedTags from 'components/ui/FetchedTags.vue';
import ItemDescriptorProxy from 'src/pages/Item/Card/ItemDescriptorProxy.vue';
import { ref } from 'vue';
const emit = defineEmits(['onDialogClosed', 'itemReplaced']);
const popupProxyRef = ref(null);
const $props = defineProps({
itemLack: {
@ -24,7 +26,7 @@ const $props = defineProps({
});
</script>
<template>
<QPopupProxy>
<QPopupProxy ref="popupProxyRef">
<QCard>
<QCardSection class="row items-center q-pb-none">
<span class="text-h6 text-grey">{{ $t('Item proposal') }}</span>
@ -43,7 +45,12 @@ const $props = defineProps({
<QCardSection class="q-pt-none"> -->
<ItemProposal
v-bind="$props"
@item-replaced="(data) => emit('itemReplaced', data)"
@item-replaced="
(data) => {
emit('itemReplaced', data);
popupProxyRef.value.hide();
}
"
></ItemProposal
></QCardSection>
</QCard>

View File

@ -3,6 +3,7 @@ import { computed, onMounted, onUnmounted, ref } from 'vue';
import { useI18n } from 'vue-i18n';
import ChangeQuantityDialog from 'pages/Ticket/Negative/components/ChangeQuantityDialog.vue';
import ChangeStateDialog from 'pages/Ticket/Negative/components/ChangeStateDialog.vue';
import ChangeItemDialog from 'pages/Ticket/Negative/components/ChangeItemDialog.vue';
import FetchedTags from 'components/ui/FetchedTags.vue';
import ItemDescriptorProxy from 'src/pages/Item/Card/ItemDescriptorProxy.vue';
import VnSubToolbar from 'src/components/ui/VnSubToolbar.vue';
@ -24,6 +25,7 @@ const editableStates = ref([]);
const stateStore = useStateStore();
const proposalDialogRef = ref();
const tableRef = ref();
const changeItemDialogRef = ref();
const changeStateDialogRef = ref();
const changeQuantityDialogRef = ref();
const showProposalDialog = ref(false);
@ -137,6 +139,16 @@ function onTicketLackFetched(data) {
<VnSubToolbar>
<template #st-data>
<QBtnGroup push style="column-gap: 1px">
<TicketMassiveUpdate
:disable="selectedRows.length < 2"
:label="t('negative.buttonsUpdate.item')"
:tooltip="t('negative.detail.modal.changeItem.title')"
>
<ChangeItemDialog
ref="changeItemDialogRef"
:selected-rows="selectedRows"
></ChangeItemDialog>
</TicketMassiveUpdate>
<TicketMassiveUpdate
:disable="selectedRows.length < 2"
:label="t('negative.buttonsUpdate.state')"

View File

@ -0,0 +1,90 @@
<script setup>
import { ref } from 'vue';
import { useI18n } from 'vue-i18n';
import axios from 'axios';
import { useDialogPluginComponent } from 'quasar';
import VnSelect from 'src/components/common/VnSelect.vue';
import FetchData from 'components/FetchData.vue';
const editableItems = ref([]);
const { t } = useI18n();
const showChangeItemDialog = ref(false);
const newItem = ref(null);
const { dialogRef } = useDialogPluginComponent();
const $props = defineProps({
selectedRows: {
type: Array,
default: () => [],
},
});
const updateItem = async () => {
try {
showChangeItemDialog.value = true;
const rowsToUpdate = $props.selectedRows.map(({ ticketFk }) =>
axios.post(`Tickets/state`, {
ticketFk,
code: newItem.value,
})
);
await Promise.all(rowsToUpdate);
} catch (err) {
return err;
} finally {
dialogRef.value.hide({ type: 'refresh', refresh: true });
}
};
</script>
<template>
<FetchData
url="State/editableStates"
@on-fetch="(data) => (editableItems = data)"
auto-load
/>
<QCard class="q-pa-sm">
<QCardSection class="row items-center justify-center column items-stretch">
<span>{{ t('negative.detail.modal.changeItem.title') }}</span>
<VnSelect
:label="t('negative.detail.modal.changeItem.placeholder')"
v-model="newItem"
:options="editableItems"
option-label="name"
option-value="code"
/>
</QCardSection>
<QCardActions align="right">
<QBtn :label="t('globals.cancel')" color="primary" flat v-close-popup />
<QBtn
:label="t('globals.confirm')"
color="primary"
:disable="!newItem"
@click="updateItem"
unelevated
autofocus
/> </QCardActions
></QCard>
</template>
<style lang="scss" scoped>
.list {
max-height: 100%;
padding: 15px;
width: 100%;
}
.grid-style-transition {
transition: transform 0.28s, background-color 0.28s;
}
#true {
background-color: $positive;
}
#false {
background-color: $negative;
}
div.q-dialog__inner > div {
max-width: fit-content !important;
}
</style>

View File

@ -211,7 +211,7 @@ negative:
totalNegative: 'Total negatives'
days: Days
buttonsUpdate:
itemProposal: Item
item: Item
state: State
quantity: Quantity
modalOrigin:
@ -245,6 +245,9 @@ negative:
changeQuantity:
title: Update tickets quantity
placeholder: New quantity
changeItem:
title: Update tickets item
placeholder: New item
split:
title: Are you sure you want to split selected tickets?
subTitle: Confirm split action