initial: bootstrap from BukidBountyApp base

This commit is contained in:
Jonathan Sykes
2026-06-06 18:43:00 +08:00
commit eb4a5731fb
5674 changed files with 160857 additions and 0 deletions

View File

@@ -0,0 +1,66 @@
<template>
<div class="home-skeleton pb-5">
<!-- BalanceBox Skeleton -->
<div class="tf-container">
<SkeletonStats />
</div>
<!-- Grid Services Skeleton -->
<div class="mt-4 px-2">
<div class="tf-container">
<div class="row g-3 justify-content-center">
<div v-for="i in 12" :key="i" class="col-3 text-center mb-4">
<SkeletonBlock width="52px" height="52px" borderRadius="14px" margin="0 auto 10px" />
<SkeletonBlock width="40px" height="10px" margin="0 auto" borderRadius="2px" />
</div>
</div>
</div>
</div>
<!-- Announcements Skeleton -->
<div class="mt-4">
<div class="tf-container">
<SkeletonBlock width="100%" height="110px" borderRadius="20px" />
</div>
</div>
<!-- Management Tools Skeleton -->
<div class="tf-container mt-5">
<div class="d-flex justify-content-between align-items-center mb-3 px-1">
<SkeletonBlock width="160px" height="22px" borderRadius="4px" />
</div>
<div v-for="i in 5" :key="i" class="d-flex align-items-center mb-3 p-3 glass-card rounded-xl border border-light-5">
<SkeletonBlock width="44px" height="44px" borderRadius="12px" margin="0 16px 0 0" />
<div class="flex-grow-1">
<SkeletonBlock width="60%" height="16px" borderRadius="4px" />
</div>
<SkeletonBlock width="24px" height="24px" borderRadius="6px" />
</div>
</div>
</div>
</template>
<script setup>
import SkeletonBlock from './SkeletonBlock.vue';
import SkeletonStats from './SkeletonStats.vue';
</script>
<style scoped>
.glass-card {
background: white;
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.05);
}
.rounded-xl {
border-radius: 20px;
}
.border-light-5 {
border-color: rgba(0, 0, 0, 0.03) !important;
}
:global(.dark-mode) .glass-card {
background: #1f2228 !important;
}
:global(.dark-mode) .border-light-5 {
border-color: rgba(255, 255, 255, 0.05) !important;
}
</style>

View File

@@ -0,0 +1,43 @@
<template>
<div class="product-list-skeleton px-2 pt-3">
<div class="row g-3 justify-content-center">
<div v-for="i in parseInt(count)" :key="i" class="col-6 col-sm-4 col-md-3">
<div class="glass-card rounded-xl overflow-hidden mb-3 border border-light-5 text-start">
<SkeletonBlock width="100%" height="140px" borderRadius="0" :noShimmer="false" />
<div class="p-3">
<SkeletonBlock width="85%" height="14px" margin="0 0 8px 0" borderRadius="3px" />
<SkeletonBlock width="60%" height="10px" margin="0 0 16px 0" borderRadius="2px" />
<div class="d-flex justify-content-between align-items-center">
<SkeletonBlock width="50px" height="12px" borderRadius="3px" />
<SkeletonBlock width="36px" height="36px" borderRadius="12px" />
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script setup>
import SkeletonBlock from './SkeletonBlock.vue';
defineProps({
count: { type: [Number, String], default: 8 }
})
</script>
<style scoped>
.glass-card {
background: white;
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.05);
}
.rounded-xl {
border-radius: 20px;
}
.border-light-5 {
border-color: rgba(0, 0, 0, 0.03) !important;
}
:global(.dark-mode) .glass-card {
background: #1f2228 !important;
}
</style>

View File

@@ -0,0 +1,17 @@
<template>
<SkeletonBlock
:width="size"
:height="size"
borderRadius="50%"
:margin="margin"
/>
</template>
<script setup>
import SkeletonBlock from './SkeletonBlock.vue';
defineProps({
size: { type: String, default: '48px' },
margin: { type: String, default: '0' }
})
</script>

View File

@@ -0,0 +1,68 @@
<template>
<div
class="skeleton-block"
:style="{
width: width,
height: height,
borderRadius: borderRadius,
margin: margin
}"
:class="{ 'shimmer': !noShimmer }"
></div>
</template>
<script setup>
defineProps({
width: { type: String, default: '100%' },
height: { type: String, default: '1rem' },
borderRadius: { type: String, default: '4px' },
margin: { type: String, default: '0' },
noShimmer: { type: Boolean, default: false }
})
</script>
<style scoped>
.skeleton-block {
background: #f0f2f5;
position: relative;
overflow: hidden;
display: block;
}
.shimmer::after {
content: "";
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
transform: translateX(-100%);
background-image: linear-gradient(
90deg,
rgba(255, 255, 255, 0) 0,
rgba(255, 255, 255, 0.2) 20%,
rgba(255, 255, 255, 0.5) 60%,
rgba(255, 255, 255, 0)
);
animation: shimmer 2s infinite;
}
:global(.dark-mode) .skeleton-block {
background: #2d3138 !important;
}
:global(.dark-mode) .shimmer::after {
background-image: linear-gradient(
90deg,
rgba(255, 255, 255, 0) 0,
rgba(255, 255, 255, 0.05) 20%,
rgba(255, 255, 255, 0.1) 60%,
rgba(255, 255, 255, 0)
);
}
@keyframes shimmer {
100% {
transform: translateX(100%);
}
}
</style>

View File

@@ -0,0 +1,38 @@
<template>
<div class="skeleton-card glass-card p-4 rounded-xl mb-4 text-start">
<div class="d-flex align-items-center mb-3">
<SkeletonAvatar size="56px" margin="0 16px 0 0" />
<div class="flex-grow-1">
<SkeletonBlock width="140px" height="20px" margin="0 0 8px 0" borderRadius="6px" />
<SkeletonBlock width="80px" height="14px" borderRadius="4px" />
</div>
</div>
<div class="divider border-bottom border-light opacity-10 mb-3"></div>
<SkeletonBlock width="100%" height="12px" margin="0 0 8px 0" borderRadius="4px" />
<SkeletonBlock width="100%" height="12px" margin="0 0 8px 0" borderRadius="4px" />
<SkeletonBlock width="60%" height="12px" borderRadius="4px" />
<div class="d-flex justify-content-between align-items-center mt-4 pt-2">
<SkeletonBlock width="100px" height="10px" borderRadius="4px" />
<SkeletonBlock width="90px" height="36px" borderRadius="18px" />
</div>
</div>
</template>
<script setup>
import SkeletonBlock from './SkeletonBlock.vue';
import SkeletonAvatar from './SkeletonAvatar.vue';
</script>
<style scoped>
.rounded-xl {
border-radius: 24px;
}
.glass-card {
background: white;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.05);
}
:global(.dark-mode) .glass-card {
background: #1f2228 !important;
}
</style>

View File

@@ -0,0 +1,44 @@
<template>
<div class="skeleton-stats glass-card p-4 rounded-xl mb-4 border text-center">
<div class="row align-items-center mb-3">
<div class="col-6 border-right">
<SkeletonBlock width="60px" height="10px" margin="0 auto 8px" borderRadius="3px" />
<SkeletonBlock width="100px" height="28px" margin="0 auto" borderRadius="6px" />
</div>
<div class="col-6">
<SkeletonBlock width="60px" height="10px" margin="0 auto 8px" borderRadius="3px" />
<SkeletonBlock width="130px" height="28px" margin="0 auto" borderRadius="6px" />
</div>
</div>
<div class="d-flex justify-content-center gap-4 mt-4 pt-3 border-top-dashed">
<SkeletonBlock v-for="i in 4" :key="i" width="44px" height="44px" borderRadius="12px" />
</div>
</div>
</template>
<script setup>
import SkeletonBlock from './SkeletonBlock.vue';
</script>
<style scoped>
.skeleton-stats {
background: white;
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.05);
}
.rounded-xl {
border-radius: 24px;
}
.border-right {
border-right: 1px solid #e9ecef;
}
.border-top-dashed {
border-top: 1px dashed #e9ecef;
}
:global(.dark-mode) .skeleton-stats {
background: #1f2228 !important;
}
:global(.dark-mode) .border-right,
:global(.dark-mode) .border-top-dashed {
border-color: rgba(255, 255, 255, 0.05) !important;
}
</style>

View File

@@ -0,0 +1,35 @@
<template>
<div class="skeleton-table rounded-3 overflow-hidden border text-start bg-white">
<div class="table-header bg-light p-3 border-bottom d-flex align-items-center">
<SkeletonBlock v-for="n in parseInt(columns)" :key="n" :width="colWidth" height="16px" margin="0 15px 0 0" borderRadius="4px" />
</div>
<div v-for="row in parseInt(rows)" :key="row" class="table-row p-3 border-bottom d-flex align-items-center">
<SkeletonBlock v-for="n in parseInt(columns)" :key="n" :width="colWidth" height="12px" margin="0 15px 0 0" borderRadius="4px" />
</div>
</div>
</template>
<script setup>
import SkeletonBlock from './SkeletonBlock.vue';
defineProps({
rows: { type: [Number, String], default: 6 },
columns: { type: [Number, String], default: 4 },
colWidth: { type: String, default: '18%' }
})
</script>
<style scoped>
.skeleton-table {
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.05);
}
.table-row:last-child {
border-bottom: none !important;
}
:global(.dark-mode) .skeleton-table {
background: #1f2228 !important;
}
:global(.dark-mode) .table-header {
background: #2d3138 !important;
}
</style>

View File

@@ -0,0 +1,28 @@
<template>
<div class="skeleton-text-container">
<SkeletonBlock
v-for="line in parseInt(lines)"
:key="line"
:width="getWidth(line)"
height="14px"
margin="0 0 8px 0"
borderRadius="4px"
/>
</div>
</template>
<script setup>
import SkeletonBlock from './SkeletonBlock.vue';
const props = defineProps({
lines: { type: [Number, String], default: 1 },
lastWidth: { type: String, default: '70%' }
})
const getWidth = (line) => {
if (parseInt(props.lines) > 1 && line === parseInt(props.lines)) {
return props.lastWidth;
}
return '100%';
}
</script>

View File

@@ -0,0 +1,15 @@
<template>
<div class="store-list-skeleton tf-container pt-3">
<div v-for="i in parseInt(count)" :key="i">
<SkeletonCard />
</div>
</div>
</template>
<script setup>
import SkeletonCard from './SkeletonCard.vue';
defineProps({
count: { type: [Number, String], default: 4 }
})
</script>

View File

@@ -0,0 +1,39 @@
<template>
<div class="transaction-list-skeleton tf-container pt-3">
<div v-for="i in parseInt(count)" :key="i" class="d-flex align-items-center mb-3 p-3 glass-card rounded-xl border border-light-5 text-start">
<SkeletonBlock width="44px" height="44px" borderRadius="12px" margin="0 16px 0 0" />
<div class="flex-grow-1">
<SkeletonBlock width="160px" height="16px" margin="0 0 6px 0" borderRadius="4px" />
<SkeletonBlock width="100px" height="12px" borderRadius="3px" />
</div>
<div class="text-end">
<SkeletonBlock width="80px" height="18px" margin="0 0 4px auto" borderRadius="4px" />
<SkeletonBlock width="50px" height="10px" margin="0 0 0 auto" borderRadius="2px" />
</div>
</div>
</div>
</template>
<script setup>
import SkeletonBlock from './SkeletonBlock.vue';
defineProps({
count: { type: [Number, String], default: 10 }
})
</script>
<style scoped>
.glass-card {
background: white;
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.05);
}
.rounded-xl {
border-radius: 20px;
}
.border-light-5 {
border-color: rgba(0, 0, 0, 0.03) !important;
}
:global(.dark-mode) .glass-card {
background: #1f2228 !important;
}
</style>