refactor: натравил форматтер на весь фронт
This commit is contained in:
@@ -27,8 +27,12 @@ const currentLevelXp = computed(() => user.value.currentLevelXp ?? 0)
|
||||
const nextLevelXp = computed(() => user.value.nextLevelXp)
|
||||
const userXp = computed(() => user.value.xp ?? 0)
|
||||
const hasLevelProgress = computed(() => nextLevelXp.value !== undefined)
|
||||
const hasNextLevel = computed(() => typeof nextLevelXp.value === 'number' && nextLevelXp.value > currentLevelXp.value)
|
||||
const levelProgressMax = computed(() => hasNextLevel.value ? nextLevelXp.value! - currentLevelXp.value : 1)
|
||||
const hasNextLevel = computed(
|
||||
() => typeof nextLevelXp.value === 'number' && nextLevelXp.value > currentLevelXp.value,
|
||||
)
|
||||
const levelProgressMax = computed(() =>
|
||||
hasNextLevel.value ? nextLevelXp.value! - currentLevelXp.value : 1,
|
||||
)
|
||||
const levelProgress = computed(() => {
|
||||
if (!hasLevelProgress.value) return 0
|
||||
if (!hasNextLevel.value) return 1
|
||||
@@ -37,27 +41,32 @@ const levelProgress = computed(() => {
|
||||
const levelProgressLabel = computed(() =>
|
||||
!hasLevelProgress.value
|
||||
? `Уровень ${user.value.level}`
|
||||
: hasNextLevel.value ? `Уровень ${user.value.level}` : `Уровень ${user.value.level} · максимум`
|
||||
: hasNextLevel.value
|
||||
? `Уровень ${user.value.level}`
|
||||
: `Уровень ${user.value.level} · максимум`,
|
||||
)
|
||||
const levelProgressText = computed(() =>
|
||||
hasNextLevel.value ? `${levelProgress.value} / ${levelProgressMax.value} XP` : `${userXp.value} XP`
|
||||
hasNextLevel.value
|
||||
? `${levelProgress.value} / ${levelProgressMax.value} XP`
|
||||
: `${userXp.value} XP`,
|
||||
)
|
||||
const activeEnrollments = computed(() => user.value.activeEnrollments ?? 0)
|
||||
const enrollmentSlotLimit = computed(() => user.value.enrollmentSlotLimit ?? 0)
|
||||
const enrollmentSlotsRemaining = computed(() =>
|
||||
Math.max(enrollmentSlotLimit.value - activeEnrollments.value, 0)
|
||||
Math.max(enrollmentSlotLimit.value - activeEnrollments.value, 0),
|
||||
)
|
||||
const enrollmentSlotRules = computed(() => user.value.enrollmentSlotRules ?? [])
|
||||
const enrollmentSlotText = computed(() =>
|
||||
enrollmentSlotLimit.value ? `${activeEnrollments.value} / ${enrollmentSlotLimit.value}` : '...'
|
||||
enrollmentSlotLimit.value ? `${activeEnrollments.value} / ${enrollmentSlotLimit.value}` : '...',
|
||||
)
|
||||
const enrollmentSlotHint = computed(() => {
|
||||
if (!enrollmentSlotLimit.value) return 'Загружаем лимит активных записей.'
|
||||
if (enrollmentSlotsRemaining.value === 0) return 'Все слоты заняты. Отмените запись, дождитесь отметки посещения или повышайте уровень.'
|
||||
if (enrollmentSlotsRemaining.value === 0)
|
||||
return 'Все слоты заняты. Отмените запись, дождитесь отметки посещения или повышайте уровень.'
|
||||
return `Можно записаться еще на ${formatLectureCount(enrollmentSlotsRemaining.value)}.`
|
||||
})
|
||||
const unlockedAchievements = computed(() => userStore.achievements.filter(a => a.unlocked))
|
||||
const lockedAchievements = computed(() => userStore.achievements.filter(a => !a.unlocked))
|
||||
const unlockedAchievements = computed(() => userStore.achievements.filter((a) => a.unlocked))
|
||||
const lockedAchievements = computed(() => userStore.achievements.filter((a) => !a.unlocked))
|
||||
const interestTags = ref([
|
||||
{ label: '#ML', active: true },
|
||||
{ label: '#ИИ', active: true },
|
||||
@@ -73,7 +82,8 @@ function formatSlotCount(slots: number) {
|
||||
const lastDigit = slots % 10
|
||||
const lastTwoDigits = slots % 100
|
||||
if (lastDigit === 1 && lastTwoDigits !== 11) return `${slots} слот`
|
||||
if (lastDigit >= 2 && lastDigit <= 4 && (lastTwoDigits < 12 || lastTwoDigits > 14)) return `${slots} слота`
|
||||
if (lastDigit >= 2 && lastDigit <= 4 && (lastTwoDigits < 12 || lastTwoDigits > 14))
|
||||
return `${slots} слота`
|
||||
return `${slots} слотов`
|
||||
}
|
||||
|
||||
@@ -81,7 +91,8 @@ function formatLectureCount(count: number) {
|
||||
const lastDigit = count % 10
|
||||
const lastTwoDigits = count % 100
|
||||
if (lastDigit === 1 && lastTwoDigits !== 11) return `${count} лекцию`
|
||||
if (lastDigit >= 2 && lastDigit <= 4 && (lastTwoDigits < 12 || lastTwoDigits > 14)) return `${count} лекции`
|
||||
if (lastDigit >= 2 && lastDigit <= 4 && (lastTwoDigits < 12 || lastTwoDigits > 14))
|
||||
return `${count} лекции`
|
||||
return `${count} лекций`
|
||||
}
|
||||
|
||||
@@ -210,16 +221,60 @@ onMounted(() => {
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.profile { display: flex; flex-direction: column; gap: 20px; }
|
||||
.header { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; }
|
||||
.profile-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); gap: 16px; }
|
||||
.user-info { display: flex; gap: 14px; align-items: center; margin-bottom: 16px; }
|
||||
.avatar { font-size: 38px; background: rgba(34,197,94,0.15); border-radius: 16px; padding: 12px; }
|
||||
.name { font-weight: 700; font-size: 18px; }
|
||||
.email, .meta { font-size: 13px; color: var(--color-text-secondary); }
|
||||
.level { margin: 16px 0; }
|
||||
.level-header { display: flex; justify-content: space-between; font-size: 12px; color: var(--color-text-secondary); margin-bottom: 6px; }
|
||||
.tags-grid { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 10px; }
|
||||
.profile {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 20px;
|
||||
}
|
||||
.header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 12px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
.profile-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
|
||||
gap: 16px;
|
||||
}
|
||||
.user-info {
|
||||
display: flex;
|
||||
gap: 14px;
|
||||
align-items: center;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
.avatar {
|
||||
font-size: 38px;
|
||||
background: rgba(34, 197, 94, 0.15);
|
||||
border-radius: 16px;
|
||||
padding: 12px;
|
||||
}
|
||||
.name {
|
||||
font-weight: 700;
|
||||
font-size: 18px;
|
||||
}
|
||||
.email,
|
||||
.meta {
|
||||
font-size: 13px;
|
||||
color: var(--color-text-secondary);
|
||||
}
|
||||
.level {
|
||||
margin: 16px 0;
|
||||
}
|
||||
.level-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
font-size: 12px;
|
||||
color: var(--color-text-secondary);
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
.tags-grid {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 6px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
.slot-overview {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@@ -273,10 +328,29 @@ onMounted(() => {
|
||||
border-color: var(--color-primary-a30);
|
||||
background: var(--color-primary-a08);
|
||||
}
|
||||
.settings { display: flex; flex-direction: column; gap: 8px; }
|
||||
.setting { font-size: 13px; color: var(--color-text-secondary); display: flex; gap: 8px; align-items: center; }
|
||||
.achievements-section { display: flex; flex-direction: column; gap: 12px; margin-top: 18px; }
|
||||
.achievements-list { display: flex; flex-direction: column; gap: 12px; }
|
||||
.settings {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
}
|
||||
.setting {
|
||||
font-size: 13px;
|
||||
color: var(--color-text-secondary);
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
align-items: center;
|
||||
}
|
||||
.achievements-section {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
margin-top: 18px;
|
||||
}
|
||||
.achievements-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
@media (max-width: 520px) {
|
||||
.slot-overview {
|
||||
|
||||
Reference in New Issue
Block a user