frontend/src/views/DetailsView.vue
nquidox bb40d17e6b
All checks were successful
/ Make image (push) Successful in 39s
details view image component refactor
2025-10-19 17:30:22 +03:00

215 lines
5.8 KiB
Vue

<script setup>
import { useMerchApi } from '@/api/merch.js'
import { onMounted, ref } from 'vue'
import router from '@/router/index.js'
import PeriodSelector from '@/components/PeriodSelector.vue'
import ChartBlock from '@/components/ChartBlock.vue'
import { useChartsApi } from '@/api/charts.js'
import EditLink from '@/views/DetailsView/EditLink.vue'
import CopyToClipboard from '@/components/CopyToClipboard.vue'
import DetailsViewImages from '@/views/DetailsView/DetailsViewImages.vue'
const { getMerchDetails, deleteMerch } = useMerchApi()
const { getDistinctPrices } = useChartsApi()
const props = defineProps({
merch_uuid: {
type: String,
required: true,
},
})
const editing = ref({
surugaya: false,
mandarake: false,
})
const merchDetails = ref(null)
const loading = ref(true)
const error = ref(null)
const fetchMerch = async () => {
try {
const response = await getMerchDetails(props.merch_uuid)
merchDetails.value = response.data
if (!response.status === 400) {
router.push({ name: 'collection' })
}
} catch (err) {
error.value = err.message
} finally {
loading.value = false
}
}
const showModal = ref(false)
const onDelete = () => {
showModal.value = true
}
const confirmDelete = async () => {
try {
const response = await deleteMerch(props.merch_uuid)
if (!response.status === 200) throw new Error('Network response was not ok')
if (!response.status === 400) router.push({ name: 'collection' })
} catch (error) {
console.log(error)
}
showModal.value = false
router.push({ name: 'collection' })
}
const prices = ref(null)
const loading2 = ref(true)
const error2 = ref(null)
const fetchPrices = async (days = 7) => {
loading2.value = true
error2.value = null
try {
const response = await getDistinctPrices(props.merch_uuid, days)
if (response.status === 400) {
router.push({ name: 'collection' })
return
}
prices.value = response.data
} catch (err) {
error2.value = err.message || 'Fetch data error'
} finally {
loading2.value = false
}
}
function handleLinkUpdate(origin, newLink) {
merchDetails.value[`origin_${origin}`].link = newLink
editing.value[origin] = false
}
function handleSelectDays(days) {
fetchPrices(days)
}
onMounted(() => {
fetchMerch()
fetchPrices(7)
})
</script>
<template>
<div v-if="loading">Loading...</div>
<div v-else-if="error">Error: {{ error }}</div>
<n-card v-else-if="merchDetails" :title="merchDetails.name">
<n-divider title-placement="left">Main</n-divider>
<div class="container-stackable">
<div>
<p><strong>Uuid:</strong> {{ merchDetails.merch_uuid }}</p>
<p><strong>Name:</strong> {{ merchDetails.name }}</p>
</div>
<DetailsViewImages :merch-uuid="merchDetails.merch_uuid"/>
</div>
<n-divider title-placement="left">Prices</n-divider>
<PeriodSelector @days="handleSelectDays" />
<div style="height: 400px; position: relative">
<ChartBlock :charts-data="prices" />
</div>
<!-- Surugaya -->
<CopyToClipboard :text="merchDetails.origin_surugaya?.link">
<n-divider title-placement="left">Surugaya</n-divider>
</CopyToClipboard>
<div v-if="!editing.surugaya">
<template v-if="merchDetails.origin_surugaya?.link">
<a
:href="merchDetails.origin_surugaya.link"
target="_blank"
rel="noopener"
class="default-color"
>
{{ merchDetails.origin_surugaya.link }}
</a>
<n-button type="primary" style="margin-left: 8px" @click="editing.surugaya = true">
Edit link
</n-button>
</template>
<template v-else>
<span class="default-color underline link-like-text" @click="editing.surugaya = true"
>Add link</span
>
</template>
</div>
<EditLink
v-else
:merch-uuid="merch_uuid"
origin="surugaya"
:name="merchDetails.name"
:model-value="merchDetails.origin_surugaya?.link || ''"
@update:model-value="handleLinkUpdate('surugaya', $event)"
@cancel-edit="editing.surugaya = false"
/>
<!-- Mandarake -->
<CopyToClipboard :text="merchDetails.origin_mandarake?.link">
<n-divider title-placement="left">Mandarake</n-divider>
</CopyToClipboard>
<div v-if="!editing.mandarake">
<template v-if="merchDetails.origin_mandarake?.link">
<a
:href="merchDetails.origin_mandarake.link"
target="_blank"
rel="noopener"
class="default-color"
>
{{ merchDetails.origin_mandarake.link }}
</a>
<n-button type="primary" style="margin-left: 8px" @click="editing.mandarake = true">
Edit link
</n-button>
</template>
<template v-else>
<span class="default-color underline link-like-text" @click="editing.mandarake = true"
>Add link</span
>
</template>
</div>
<EditLink
v-else
:merch-uuid="merch_uuid"
origin="mandarake"
:name="merchDetails.name"
:model-value="merchDetails.origin_mandarake?.link || ''"
@update:model-value="handleLinkUpdate('mandarake', $event)"
@cancel-edit="editing.mandarake = false"
/>
</n-card>
<div v-else>Not found</div>
<div class="button-container-center">
<n-button type="error" class="center-button" @click="onDelete">Delete</n-button>
</div>
<n-modal v-model:show="showModal" preset="dialog" title="Confirmation">
<template #default>
<p>Confirm delete</p>
</template>
<template #action>
<n-button @click="confirmDelete" type="error">Ok</n-button>
<n-button @click="showModal = false">Cancel</n-button>
</template>
</n-modal>
</template>
<style scoped>
.container-stackable {
display: flex;
flex-wrap: wrap;
gap: 10px;
justify-content: space-between;
}
</style>