feat(magic): add IosStarRating and CooldownCountdown components
This commit is contained in:
parent
8953e1f7d6
commit
118269a8c9
37
apps/rebreak-magic/app/components/CooldownCountdown.vue
Normal file
37
apps/rebreak-magic/app/components/CooldownCountdown.vue
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
<template>
|
||||||
|
<span class="text-amber-700 font-semibold tabular-nums">
|
||||||
|
{{ display }}
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, computed, onMounted, onUnmounted } from "vue";
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
until: string;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const now = ref(Date.now());
|
||||||
|
let timer: ReturnType<typeof setInterval> | null = null;
|
||||||
|
|
||||||
|
const remainingMs = computed(() => Math.max(0, new Date(props.until).getTime() - now.value));
|
||||||
|
|
||||||
|
const display = computed(() => {
|
||||||
|
const totalSec = Math.floor(remainingMs.value / 1000);
|
||||||
|
const h = Math.floor(totalSec / 3600);
|
||||||
|
const m = Math.floor((totalSec % 3600) / 60);
|
||||||
|
const s = totalSec % 60;
|
||||||
|
if (h > 0) return `${h}h ${String(m).padStart(2, "0")}m`;
|
||||||
|
return `${String(m).padStart(2, "0")}:${String(s).padStart(2, "0")}`;
|
||||||
|
});
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
timer = setInterval(() => {
|
||||||
|
now.value = Date.now();
|
||||||
|
}, 1000);
|
||||||
|
});
|
||||||
|
|
||||||
|
onUnmounted(() => {
|
||||||
|
if (timer) clearInterval(timer);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
25
apps/rebreak-magic/app/components/IosStarRating.vue
Normal file
25
apps/rebreak-magic/app/components/IosStarRating.vue
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
<template>
|
||||||
|
<div class="flex items-center gap-1" :title="tooltip">
|
||||||
|
<UIcon
|
||||||
|
v-for="(star, i) in stars"
|
||||||
|
:key="i"
|
||||||
|
name="i-heroicons-star"
|
||||||
|
class="w-4 h-4"
|
||||||
|
:class="star ? 'text-amber-400' : 'text-gray-200'"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
const props = defineProps<{
|
||||||
|
enrollment: boolean;
|
||||||
|
sideload: boolean;
|
||||||
|
app: boolean;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const stars = computed(() => [props.enrollment, props.sideload, props.app]);
|
||||||
|
const tooltip = computed(() => {
|
||||||
|
const labels = ["Enrollment", "Sideload", "ReBreak App"];
|
||||||
|
return stars.value.map((ok, i) => `${labels[i]}: ${ok ? "✓" : "✗"}`).join(" · ");
|
||||||
|
});
|
||||||
|
</script>
|
||||||
Loading…
x
Reference in New Issue
Block a user