update origin link component
This commit is contained in:
parent
60e1abc941
commit
2249775e2a
3 changed files with 160 additions and 3 deletions
138
src/views/DetailsView/EditLink.vue
Normal file
138
src/views/DetailsView/EditLink.vue
Normal file
|
|
@ -0,0 +1,138 @@
|
|||
<script setup>
|
||||
import { ref, nextTick, watch, computed } from 'vue'
|
||||
import { useMerchApi } from '@/api/merch.js'
|
||||
|
||||
const { updateMerch } = useMerchApi()
|
||||
|
||||
const props = defineProps({
|
||||
modelValue: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
default: 'text'
|
||||
},
|
||||
placeholder: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
emptyText: {
|
||||
type: String,
|
||||
default: 'Add link'
|
||||
},
|
||||
merchUuid: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
name: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
origin: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
})
|
||||
|
||||
const emit = defineEmits(['update:modelValue'])
|
||||
|
||||
const isEditing = ref(false)
|
||||
const tempValue = ref('')
|
||||
const inputRef = ref(null)
|
||||
const loading = ref(false)
|
||||
|
||||
const displayValue = computed(() => {
|
||||
const val = props.modelValue.trim()
|
||||
return val === '' || val == null ? props.emptyText : props.modelValue
|
||||
})
|
||||
|
||||
const startEditing = () => {
|
||||
tempValue.value = props.modelValue
|
||||
isEditing.value = true
|
||||
nextTick(() => {
|
||||
inputRef.value?.focus?.()
|
||||
})
|
||||
}
|
||||
|
||||
const save = async () => {
|
||||
const newValue = tempValue.value.trim()
|
||||
if (newValue !== props.modelValue) {
|
||||
emit('update:modelValue', newValue)
|
||||
}
|
||||
isEditing.value = false
|
||||
loading.value = true
|
||||
|
||||
try {
|
||||
await updateMerch({
|
||||
merch_uuid: props.merchUuid,
|
||||
name: props.name,
|
||||
origin: props.origin,
|
||||
link: newValue
|
||||
})
|
||||
|
||||
emit('update:modelValue', newValue)
|
||||
} catch (error) {
|
||||
console.error('Update link error:', error)
|
||||
} finally {
|
||||
loading.value = false
|
||||
isEditing.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const cancel = () => {
|
||||
isEditing.value = false
|
||||
}
|
||||
|
||||
watch(() => props.modelValue, (newVal) => {
|
||||
if (isEditing.value) {
|
||||
tempValue.value = newVal
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
||||
<span v-if="!isEditing" @click="startEditing" class="editable-text">
|
||||
{{ displayValue }}
|
||||
</span>
|
||||
<div v-else class="editing-area">
|
||||
<n-input
|
||||
v-model:value="tempValue"
|
||||
type="text"
|
||||
size="small"
|
||||
ref="inputRef"
|
||||
@keyup.enter="save"
|
||||
@keyup.esc="cancel"
|
||||
:placeholder="placeholder || 'Enter link here...'"
|
||||
/>
|
||||
<n-button size="small" type="primary" @click="save">✓</n-button>
|
||||
<n-button size="small" @click="cancel">✕</n-button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.editable-text {
|
||||
cursor: pointer;
|
||||
text-decoration: underline;
|
||||
color: #18a058;
|
||||
padding: 2px 4px;
|
||||
border-radius: 4px;
|
||||
transition: background 0.2s;
|
||||
min-height: 1.2em;
|
||||
display: inline-block;
|
||||
min-width: 50px;
|
||||
}
|
||||
|
||||
.editable-text:hover {
|
||||
background-color: #f0f9ff;
|
||||
}
|
||||
|
||||
.editing-area {
|
||||
display: inline-flex;
|
||||
gap: 6px;
|
||||
align-items: center;
|
||||
vertical-align: middle;
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
Loading…
Add table
Add a link
Reference in a new issue