TEST UPD
- add load more - add front
This commit is contained in:
@@ -12,95 +12,121 @@
|
||||
<h2 class="text-lg text-ink-gray-9 font-semibold">Мои баллы</h2>
|
||||
|
||||
<!-- Загрузка -->
|
||||
<div v-if="energyPoints.loading" class="text-center py-16 text-gray-600">
|
||||
<div v-if="energyPoints.loading && !hasMoreData" class="text-center py-16 text-gray-600">
|
||||
Загружаем баллы...
|
||||
</div>
|
||||
|
||||
<!-- Нет баллов -->
|
||||
<div v-else-if="!energyPoints.data?.length" class="bg-white rounded-xl shadow p-12 text-center">
|
||||
<div v-else-if="!displayedPoints.length" class="bg-white rounded-xl shadow p-12 text-center">
|
||||
<p class="text-xl text-gray-600">У вас пока нет баллов</p>
|
||||
<p class="text-sm text-gray-500 mt-2">Участвуйте в активностях — баллы появятся!</p>
|
||||
</div>
|
||||
|
||||
<!-- Есть баллы -->
|
||||
<div v-else>
|
||||
<!-- Есть баллы -->
|
||||
<div v-else>
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-8">
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-8">
|
||||
<!-- ЛЕВАЯ КОЛОНКА — список баллов -->
|
||||
<div class="bg-white rounded-xl shadow-xl mt-4">
|
||||
<ul class="divide-y divide-gray-200">
|
||||
<li v-for="item in displayedPoints" :key="item.name" class="p-6 hover:bg-gray-50 transition">
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="flex items-center gap-5">
|
||||
<div class="text-2xl font-bold"
|
||||
:class="item.points > 0 ? 'text-green-600' : 'text-red-600'">
|
||||
{{ item.points > 0 ? '+' : '' }}{{ item.points }}
|
||||
</div>
|
||||
|
||||
<!-- ЛЕВАЯ КОЛОНКА — список баллов -->
|
||||
<div class="bg-white rounded-xl shadow-xl mt-4">
|
||||
<ul class="divide-y divide-gray-200">
|
||||
<li v-for="item in energyPoints.data.slice(0, 20)" :key="item.name" class="p-6 hover:bg-gray-50">
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="flex items-center gap-5">
|
||||
<div class="text-2xl font-bold"
|
||||
:class="item.points > 0 ? 'text-green-600' : 'text-red-600'">
|
||||
{{ item.points > 0 ? '+' : '' }}{{ item.points }}
|
||||
</div>
|
||||
<div>
|
||||
<p class="font-medium text-gray-900">
|
||||
{{ item.rule || 'Начисление баллов' }}
|
||||
</p>
|
||||
<p class="text-sm text-gray-500">
|
||||
{{ dayjs(item.creation).format('DD MMMM YYYY в HH:mm') }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div>
|
||||
<p class="font-medium text-gray-900">
|
||||
{{ item.rule || 'Начисление баллов' }}
|
||||
</p>
|
||||
<p class="text-sm text-gray-500">
|
||||
{{ dayjs(item.creation).format('DD MMMM YYYY в HH:mm') }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<!-- Кнопка "Загрузить ещё" -->
|
||||
<div v-if="hasMoreData" class="p-4 border-t">
|
||||
<button
|
||||
@click="loadMore"
|
||||
:disabled="energyPoints.loading"
|
||||
class="w-full py-3 px-4 bg-teal-600 hover:bg-teal-700 disabled:bg-gray-300 text-white font-medium rounded-lg transition flex items-center justify-center gap-2"
|
||||
>
|
||||
<span v-if="energyPoints.loading">Загружаем...</span>
|
||||
<span v-else>Загрузить ещё</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- ПРАВАЯ КОЛОНКА — итоги -->
|
||||
<div class="space-y-6">
|
||||
<div class="bg-white rounded-xl p-6 shadow-xl mt-4">
|
||||
<p class="text-lg opacity-90">Всего баллов</p>
|
||||
<p class="text-5xl font-bold mt-3">{{ totalPoints }}</p>
|
||||
</div>
|
||||
<!-- Сообщение, если всё загружено -->
|
||||
<div v-if="!hasMoreData && displayedPoints.length > 10" class="p-4 text-center text-gray-500 text-sm border-t">
|
||||
Все записи загружены ({{ displayedPoints.length }})
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="bg-green-600 rounded-xl p-6 shadow-xl mt-4">
|
||||
<p class="text-lg opacity-90">Дополнительно при поступлении в МПГУ</p>
|
||||
<p class="text-5xl font-bold mt-3">+{{ additionalPoints }}</p>
|
||||
<p class="text-sm opacity-80 mt-3">максимум 10 баллов</p>
|
||||
</div>
|
||||
</div>
|
||||
<!-- ПРАВАЯ КОЛОНКА — итоги -->
|
||||
<div class="space-y-6 text-teal-600">
|
||||
<div class="bg-teal-500/60 rounded-xl p-6 shadow-xl mt-4">
|
||||
<p class="text-lg opacity-90">Всего баллов</p>
|
||||
<p class="text-2xl font-bold mt-3">{{ totalPoints }}</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="bg-teal-500/60 rounded-xl p-6 shadow-xl mt-4">
|
||||
<p class="text-lg opacity-90">Дополнительно при поступлении в МПГУ</p>
|
||||
<p class="text-2xl font-bold mt-3">+{{ additionalPoints }}</p>
|
||||
<p class="text-sm opacity-80 mt-3">Максимум можно получить 10 баллов</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { inject, computed, onMounted } from 'vue'
|
||||
import { inject, computed, ref, onMounted } from 'vue'
|
||||
import { createResource, Breadcrumbs } from 'frappe-ui'
|
||||
import NoPermission from '@/components/NoPermission.vue'
|
||||
|
||||
const $user = inject('$user')
|
||||
const dayjs = inject('$dayjs')
|
||||
|
||||
// Главное — фильтруем по email, как в LMS!
|
||||
// Параметры пагинации
|
||||
const pageSize = 15
|
||||
const currentPage = ref(1)
|
||||
const allPoints = ref([]) // все загруженные записи
|
||||
|
||||
// Ресурс с динамическими параметрами
|
||||
const energyPoints = createResource({
|
||||
url: 'frappe.client.get_list',
|
||||
params: {
|
||||
doctype: 'Energy Point Log',
|
||||
fields: ['name', 'points', 'rule', 'creation'],
|
||||
filters: {
|
||||
user: $user.data.email // ← вот так, как в LMS — по email!
|
||||
},
|
||||
filters: { user: $user.data.email },
|
||||
order_by: 'creation desc',
|
||||
limit_page_length: 1000
|
||||
limit_page_length: pageSize,
|
||||
start: 0
|
||||
},
|
||||
auto: false,
|
||||
onSuccess(data) {
|
||||
console.log('Баллы загружены:', data.length, 'записей')
|
||||
if (currentPage.value === 1) {
|
||||
allPoints.value = data
|
||||
} else {
|
||||
allPoints.value = [...allPoints.value, ...data]
|
||||
}
|
||||
hasMoreData.value = data.length === pageSize
|
||||
}
|
||||
})
|
||||
|
||||
// Вычисляемые значения
|
||||
const displayedPoints = computed(() => allPoints.value)
|
||||
|
||||
const totalPoints = computed(() => {
|
||||
const list = Array.isArray(energyPoints.data) ? energyPoints.data : []
|
||||
return list.reduce((sum, item) => sum + (item.points || 0), 0)
|
||||
return allPoints.value.reduce((sum, item) => sum + (item.points || 0), 0)
|
||||
})
|
||||
|
||||
const additionalPoints = computed(() => {
|
||||
@@ -108,13 +134,26 @@ const additionalPoints = computed(() => {
|
||||
return bonus < 10 ? bonus : 10
|
||||
})
|
||||
|
||||
const hasMoreData = ref(true)
|
||||
|
||||
const breadcrumbs = computed(() => [
|
||||
{ label: 'Главная', route: '/' },
|
||||
{ label: 'Мои баллы' }
|
||||
])
|
||||
|
||||
// Функция загрузки следующей страницы
|
||||
const loadMore = () => {
|
||||
if (!hasMoreData.value || energyPoints.loading) return
|
||||
|
||||
currentPage.value += 1
|
||||
energyPoints.params.start = (currentPage.value - 1) * pageSize
|
||||
energyPoints.fetch()
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
if ($user.data) {
|
||||
currentPage.value = 1
|
||||
energyPoints.params.start = 0
|
||||
energyPoints.fetch()
|
||||
}
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user