felhasználói felületre pü

This commit is contained in:
Roo
2026-07-27 08:39:18 +00:00
parent c9118bf52f
commit 6f28d3e70d
72 changed files with 6311 additions and 749 deletions

View File

@@ -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>