felhasználói felületre pü
This commit is contained in:
@@ -215,6 +215,65 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Inactivity Monitor -->
|
||||
<div class="bg-slate-800 rounded-xl border border-slate-700 p-6">
|
||||
<h2 class="text-lg font-semibold text-white mb-4 flex items-center gap-2">
|
||||
<svg class="w-5 h-5 text-rose-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.964-.833-2.732 0L4.082 16.5c-.77.833.192 2.5 1.732 2.5z" />
|
||||
</svg>
|
||||
{{ t('gamification.config.inactivity_monitor') }}
|
||||
</h2>
|
||||
<p class="text-sm text-slate-400 mb-6">
|
||||
{{ t('gamification.config.inactivity_desc') }}
|
||||
</p>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||
<!-- Threshold Days -->
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-slate-300 mb-2">
|
||||
{{ t('gamification.config.inactivity_threshold') }}
|
||||
</label>
|
||||
<div class="flex items-center gap-3">
|
||||
<input
|
||||
v-model.number="inactivityDays"
|
||||
type="number"
|
||||
min="30"
|
||||
max="730"
|
||||
class="w-32 px-3 py-2 bg-slate-700 border border-slate-600 rounded-lg text-white text-center focus:outline-none focus:ring-2 focus:ring-amber-500/50 focus:border-amber-500 text-sm"
|
||||
/>
|
||||
<span class="text-sm text-slate-400">{{ t('gamification.config.days') }}</span>
|
||||
</div>
|
||||
<p class="text-xs text-slate-500 mt-1.5">
|
||||
{{ t('gamification.config.inactivity_range') }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Current effective value -->
|
||||
<div class="flex items-end">
|
||||
<div class="bg-slate-700/50 rounded-lg px-4 py-3 w-full">
|
||||
<div class="text-xs text-slate-500 uppercase tracking-wider mb-1">{{ t('gamification.config.effective_threshold') }}</div>
|
||||
<div class="text-lg font-semibold text-white">{{ inactivityDays || 180 }} {{ t('gamification.config.days') }}</div>
|
||||
<div class="text-xs text-slate-500 mt-0.5">
|
||||
{{ t('gamification.config.last_changed') }}: {{ lastUpdated || t('gamification.config.never') }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Save Button -->
|
||||
<div class="mt-6 flex items-center gap-4">
|
||||
<button
|
||||
@click="saveInactivityThreshold"
|
||||
class="px-4 py-2 bg-amber-600 hover:bg-amber-500 text-white rounded-lg text-sm font-medium transition"
|
||||
>
|
||||
{{ t('gamification.config.save_inactivity') }}
|
||||
</button>
|
||||
<span v-if="inactivityDays !== originalInactivityDays" class="text-xs text-amber-400">
|
||||
{{ t('gamification.config.has_changes') }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Impact Calculator -->
|
||||
<div class="bg-slate-800 rounded-xl border border-slate-700 p-6 mb-8">
|
||||
<h2 class="text-lg font-semibold text-white mb-4 flex items-center gap-2">
|
||||
@@ -387,6 +446,10 @@ const penaltyLogic = reactive<PenaltyLogic>({
|
||||
const conversionLogic = reactive<ConversionLogic>({ socialToCreditRate: 100 })
|
||||
const levelRewards = reactive<LevelRewards>({ creditsPer10Levels: 50 })
|
||||
|
||||
const inactivityDays = ref(180)
|
||||
const originalInactivityDays = ref(180)
|
||||
const lastUpdated = ref<string | null>(null)
|
||||
|
||||
const calculator = reactive({ level: 5, activities: 3, socialPoints: 50 })
|
||||
|
||||
const calculatedDailyXp = computed(() => {
|
||||
@@ -468,6 +531,45 @@ function applyConfigToForm(cfg: Record<string, any>) {
|
||||
}
|
||||
}
|
||||
|
||||
async function fetchInactivityThreshold() {
|
||||
try {
|
||||
const data = await $fetch<{ key: string; value: any }>('/api/v1/system/parameters/inactivity_threshold_days?scope_level=global', {
|
||||
headers: getHeaders(),
|
||||
})
|
||||
const val = data.value
|
||||
if (typeof val === 'object' && val !== null) {
|
||||
inactivityDays.value = Number(val.value || val.days || 180)
|
||||
} else {
|
||||
inactivityDays.value = Number(val) || 180
|
||||
}
|
||||
originalInactivityDays.value = inactivityDays.value
|
||||
lastUpdated.value = (data as any).updated_at ? new Date((data as any).updated_at).toLocaleDateString('hu-HU') : null
|
||||
} catch (e) {
|
||||
// Parameter not seeded yet — default stays 180
|
||||
inactivityDays.value = 180
|
||||
originalInactivityDays.value = 180
|
||||
}
|
||||
}
|
||||
|
||||
async function saveInactivityThreshold() {
|
||||
try {
|
||||
await $fetch('/api/v1/system/parameters/inactivity_threshold_days?scope_level=global', {
|
||||
method: 'PUT',
|
||||
headers: getHeaders(),
|
||||
body: {
|
||||
value: inactivityDays.value,
|
||||
description: 'User inactivity threshold in days. If last activity is older, account is suspended and MLM commission bypasses them.',
|
||||
},
|
||||
})
|
||||
originalInactivityDays.value = inactivityDays.value
|
||||
showToast(t('gamification.config.inactivity_updated'))
|
||||
} catch (e) {
|
||||
console.error('Failed to save inactivity threshold:', e)
|
||||
formError.value = t('gamification.config.inactivity_save_error')
|
||||
setTimeout(() => { formError.value = '' }, 4000)
|
||||
}
|
||||
}
|
||||
|
||||
async function fetchConfig() {
|
||||
loading.value = true
|
||||
error.value = false
|
||||
@@ -525,6 +627,7 @@ function formatNumber(n: number): string {
|
||||
|
||||
onMounted(() => {
|
||||
fetchConfig()
|
||||
fetchInactivityThreshold()
|
||||
})
|
||||
</script>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user