big ui refractor
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
<template lang="pug">
|
||||
v-card.pa-4.widget-card.rounded-xl.border-subtle.d-flex.flex-column(
|
||||
v-card.pa-4.widget-card.rounded-xl.d-flex.flex-column(
|
||||
color="#1e1e24"
|
||||
flat
|
||||
)
|
||||
@@ -38,5 +38,3 @@ const props = defineProps({
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
const hasHeader = computed(() => !!props.title || !!props.icon || !!props.subtitle);
|
||||
</script>
|
||||
|
||||
<style lang="scss" src="@/styles/components/_widgets.scss" scoped></style>
|
||||
|
||||
@@ -35,5 +35,3 @@ const accuracyPercent = computed(() => {
|
||||
return Math.round((props.accuracy.correct / props.accuracy.total) * 100);
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" src="@/styles/components/_widgets.scss" scoped></style>
|
||||
|
||||
@@ -59,5 +59,3 @@ const toRoman = (num) => {
|
||||
return lookup[num] || num;
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" src="@/styles/components/_widgets.scss" scoped></style>
|
||||
|
||||
@@ -29,5 +29,3 @@ const props = defineProps({
|
||||
|
||||
const hasUpcoming = computed(() => props.forecast && props.forecast.some((c) => c > 0));
|
||||
</script>
|
||||
|
||||
<style lang="scss" src="@/styles/components/_widgets.scss" scoped></style>
|
||||
|
||||
@@ -35,5 +35,3 @@ const props = defineProps({
|
||||
ghosts: { type: Array, default: () => [] },
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" src="@/styles/components/_widgets.scss" scoped></style>
|
||||
|
||||
@@ -39,5 +39,3 @@ const masteryPercent = computed(
|
||||
() => (totalItems.value === 0 ? 0 : Math.round((masteredCount.value / totalItems.value) * 100)),
|
||||
);
|
||||
</script>
|
||||
|
||||
<style lang="scss" src="@/styles/components/_widgets.scss" scoped></style>
|
||||
|
||||
@@ -78,5 +78,3 @@ const getHeatmapClass = (count) => {
|
||||
const formatDate = (dateStr) => new Date(dateStr).toLocaleDateString(locale.value, { month: 'short', day: 'numeric' });
|
||||
const isToday = (dateStr) => dateStr === new Date().toISOString().split('T')[0];
|
||||
</script>
|
||||
|
||||
<style lang="scss" src="@/styles/components/_widgets.scss" scoped></style>
|
||||
|
||||
@@ -58,5 +58,3 @@ const getDayLabel = (dateStr) => {
|
||||
return new Date(dateStr).toLocaleDateString(locale.value, { weekday: 'short' });
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" src="@/styles/components/_widgets.scss" scoped></style>
|
||||
|
||||
@@ -1,53 +1,72 @@
|
||||
<template lang="pug">
|
||||
.grid-area-full.text-center.mb-4
|
||||
.text-h2.font-weight-bold.mb-2 {{ $t('hero.welcome') }}
|
||||
.text-h5.text-grey.mb-8 {{ $t('hero.subtitle') }}
|
||||
.grid-area-full.text-center.mb-8.zen-wrapper
|
||||
.text-h3.font-weight-bold.mb-2.text-white.letter-spacing-small {{ $t('hero.welcome') }}
|
||||
.text-subtitle-1.text-grey-lighten-1.mb-10(
|
||||
style="max-width: 600px; margin-inline: auto;"
|
||||
) {{ $t('hero.subtitle') }}
|
||||
|
||||
.d-flex.justify-center.align-center.flex-column.gap-4
|
||||
v-btn.text-h5.font-weight-bold.text-black.glow-btn.welcome-btn(
|
||||
.d-flex.justify-center.align-stretch.flex-wrap.ga-6.mb-8
|
||||
|
||||
v-btn.zen-btn.lesson-btn(
|
||||
v-if="lessonCount > 0"
|
||||
to="/lesson"
|
||||
rounded="xl"
|
||||
color="purple-accent-2"
|
||||
class="mb-3"
|
||||
variant="tonal"
|
||||
size="x-large"
|
||||
height="80"
|
||||
)
|
||||
v-icon(size="32" start) mdi-school
|
||||
| {{ $t('hero.lessons') }}
|
||||
v-chip.ml-3.font-weight-bold(
|
||||
color="#1e1e24"
|
||||
variant="flat"
|
||||
size="default"
|
||||
style="color: white !important;"
|
||||
) {{ lessonCount }}
|
||||
v-btn.text-h5.font-weight-bold.text-black.glow-btn.welcome-btn(
|
||||
.d-flex.align-center.w-100.px-2.zen-btn-content
|
||||
v-icon.mr-5(size="36" icon="mdi-school-outline")
|
||||
|
||||
.d-flex.flex-column.align-start.mr-auto
|
||||
.text-purple-lighten-1.text-h6.font-weight-bold.line-height-tight
|
||||
| {{ $t('hero.lessons') }}
|
||||
.text-purple-accent-1.text-caption.font-weight-regular.opacity-80
|
||||
| {{ $t('hero.newContent') }}
|
||||
|
||||
.zen-counter.bg-purple-accent-2.text-black.ml-4
|
||||
| {{ lessonCount }}
|
||||
|
||||
v-btn.zen-btn.review-btn(
|
||||
@click="$emit('start', 'shuffled')"
|
||||
rounded="xl"
|
||||
color="#00cec9"
|
||||
color="cyan-accent-2"
|
||||
variant="tonal"
|
||||
size="x-large"
|
||||
height="80"
|
||||
:disabled="queueLength === 0"
|
||||
:class="{ 'zen-disabled': queueLength === 0 }"
|
||||
)
|
||||
v-icon(size="32" start) mdi-brush
|
||||
| {{ queueLength > 0 ? $t('hero.start') : $t('hero.noReviews') }}
|
||||
.d-flex.align-center.w-100.px-2.zen-btn-content
|
||||
v-icon.mr-5(size="36" icon="mdi-brush-variant")
|
||||
|
||||
v-chip.ml-3.font-weight-bold(
|
||||
v-if="queueLength > 0"
|
||||
color="#1e1e24"
|
||||
variant="flat"
|
||||
size="default"
|
||||
style="color: white !important;"
|
||||
) {{ queueLength }}
|
||||
.d-flex.flex-column.align-start.mr-auto
|
||||
.text-cyan-lighten-1.text-h6.font-weight-bold.line-height-tight
|
||||
| {{ queueLength > 0 ? $t('hero.start') : $t('hero.noReviews') }}
|
||||
.text-cyan-accent-1.text-caption.font-weight-regular.opacity-80
|
||||
| {{ queueLength > 0 ? $t('hero.readyToReview') : $t('hero.allCaughtUp') }}
|
||||
|
||||
v-fade-transition
|
||||
.zen-counter.bg-cyan-accent-2.text-black.ml-4(v-if="queueLength > 0")
|
||||
| {{ queueLength }}
|
||||
|
||||
.d-flex.justify-center.align-center.flex-column.gap-1
|
||||
v-fade-transition
|
||||
v-btn.mt-4.text-caption.font-weight-bold(
|
||||
v-btn.text-caption.font-weight-bold.text-uppercase.letter-spacing-1.text-grey(
|
||||
v-if="hasLowerLevels"
|
||||
@click="$emit('start', 'priority')"
|
||||
variant="plain"
|
||||
color="grey-lighten-1"
|
||||
variant="text"
|
||||
prepend-icon="mdi-sort-ascending"
|
||||
:ripple="false"
|
||||
) {{ $t('hero.prioritize', { count: lowerLevelCount }) }}
|
||||
|
||||
.text-caption.text-grey.mt-2(v-if="queueLength === 0")
|
||||
| {{ $t('hero.nextIn') }} {{ nextReviewTime }}
|
||||
v-fade-transition
|
||||
.text-caption.text-grey-darken-1.font-weight-medium.d-flex.align-center.mt-2(
|
||||
v-if="queueLength === 0 && !hasLowerLevels && nextReviewTime"
|
||||
)
|
||||
v-icon.mr-2(size="small" icon="mdi-clock-outline")
|
||||
span {{ $t('hero.nextIn') }} {{ nextReviewTime }}
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
@@ -67,9 +86,11 @@ defineEmits(['start']);
|
||||
const { t } = useI18n();
|
||||
|
||||
const nextReviewTime = computed(() => {
|
||||
if (!props.forecast) return 'a while';
|
||||
const idx = props.forecast.findIndex((c) => c > 0);
|
||||
if (idx === -1) return 'a while';
|
||||
return idx === 0 ? t('hero.now') : t('stats.inHours', { n: idx }, idx);
|
||||
if (!props.forecast || Object.keys(props.forecast).length === 0) return null;
|
||||
try {
|
||||
const idx = props.forecast.findIndex((c) => c > 0);
|
||||
if (idx === -1) return null;
|
||||
return idx === 0 ? t('hero.now') : t('stats.inHours', { n: idx }, idx);
|
||||
} catch (e) { return null; }
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -121,6 +121,7 @@ watch(() => props.char, (newChar) => {
|
||||
|
||||
watch(() => props.autoHint, (shouldHint) => {
|
||||
if (!controller) return;
|
||||
controller.setAutoHint(shouldHint);
|
||||
if (shouldHint) controller.showHint();
|
||||
});
|
||||
|
||||
|
||||
@@ -58,6 +58,7 @@ const props = defineProps({
|
||||
default: 'animate',
|
||||
validator: (v) => ['hero', 'animate'].includes(v),
|
||||
},
|
||||
svgContent: { type: String, default: '' },
|
||||
});
|
||||
|
||||
const strokes = ref([]);
|
||||
@@ -72,10 +73,14 @@ async function loadData(char) {
|
||||
const hex = char.charCodeAt(0).toString(16).padStart(5, '0');
|
||||
|
||||
try {
|
||||
const baseUrl = 'https://raw.githubusercontent.com/KanjiVG/kanjivg/master/kanji';
|
||||
const res = await fetch(`${baseUrl}/${hex}.svg`);
|
||||
let txt = props.svgContent;
|
||||
|
||||
if (!txt) {
|
||||
const baseUrl = 'https://raw.githubusercontent.com/KanjiVG/kanjivg/master/kanji';
|
||||
const res = await fetch(`${baseUrl}/${hex}.svg`);
|
||||
txt = await res.text();
|
||||
}
|
||||
|
||||
const txt = await res.text();
|
||||
const parser = new DOMParser();
|
||||
const doc = parser.parseFromString(txt, 'image/svg+xml');
|
||||
const rawPaths = Array.from(doc.getElementsByTagName('path')).map((p) => p.getAttribute('d'));
|
||||
@@ -147,5 +152,3 @@ defineExpose({ playAnimation });
|
||||
onMounted(() => { if (props.char) loadData(props.char); });
|
||||
watch(() => props.char, (n) => { if (n) loadData(n); });
|
||||
</script>
|
||||
|
||||
<style lang="scss" src="@/styles/components/_kanji.scss" scoped></style>
|
||||
|
||||
Reference in New Issue
Block a user