#6321 - Negative ticket #158
|
@ -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>
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
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
jgallego
commented
30 ? 30 ?
jsegarra
commented
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%;
|
||||
}
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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')"
|
||||
|
|
|
@ -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>
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue
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
ok, vale, cambio de style por class