This commit is contained in:
11
AGENTS.md
11
AGENTS.md
@@ -6,7 +6,7 @@ Monorepo for aranroig.com — a personal portfolio website with blog, art galler
|
||||
|
||||
- **Frontend**: Nuxt 4 + Vue 3 + TypeScript + SCSS
|
||||
- **Backend**: Express 5 + Mongoose (MongoDB)
|
||||
- **i18n**: @nuxtjs/i18n (English, Spanish, Catalan)
|
||||
- **i18n**: @nuxtjs/i18n (English, Spanish, Catalan, Chinese)
|
||||
- **Content**: Nuxt Content v3 with Zod-sourced Markdown collections
|
||||
- **Image optimization**: @nuxt/image
|
||||
- **Build**: Vite
|
||||
@@ -27,15 +27,15 @@ Monorepo for aranroig.com — a personal portfolio website with blog, art galler
|
||||
│ │ │ ├── layouts/ # Page layout wrappers
|
||||
│ │ │ ├── parts/ # Header, footer, navigation pieces
|
||||
│ │ │ └── content/ # Blog, art content components
|
||||
│ │ ├── composables/ # useApi(), theme.ts (light/dark + accent colors)
|
||||
│ │ ├── composables/ # useApi(), useAuth(), theme.ts (light/dark + accent colors)
|
||||
│ │ ├── i18n.config.ts# VueI18n fallback locale setup
|
||||
│ │ └── pages/ # File-based routing (index, blog, art, contact)
|
||||
│ │ └── pages/ # File-based routing (index, blog, art, contact, admin)
|
||||
│ ├── content/ # Markdown collections organized by locale
|
||||
│ │ ├── fixed/ # Static pages per locale
|
||||
│ │ ├── blog/ # Blog posts
|
||||
│ │ ├── art/ # Art pieces
|
||||
│ │ └── projects/ # Project cards
|
||||
│ ├── i18n/locales/ # en.json, es.json, ca.json translation files
|
||||
│ ├── i18n/locales/ # en.json, es.json, ca.json, zh.json translation files
|
||||
│ ├── content.config.ts # Content collection schemas (Zod)
|
||||
│ └── nuxt.config.ts # Nuxt config: modules, i18n, runtime config
|
||||
├── docker-compose.yml # Services: nginx, frontend, backend
|
||||
@@ -75,6 +75,7 @@ In `backend/`:
|
||||
- Backend reads `.env.development` or `.env.production` based on `NODE_ENV`. Requires `DB_URI` for MongoDB.
|
||||
- Frontend runtime config key `public.apiBaseUrl` sets the backend API URL used by `useApi()`.
|
||||
- Content lives in `frontend/content/` under collection folders (`blog`, `fixed`, `art`, `projects`), each with locale subdirectories (`en`, `es`, `ca`).
|
||||
- Admin panel lives at `/admin` (login, dashboard, orders), guarded by the `admin-auth` middleware and the `admin_token` cookie. Admin pages share the `AdminLayout` shell with the `AdminSidebar`.
|
||||
|
||||
## Code Style
|
||||
|
||||
@@ -84,6 +85,8 @@ In `backend/`:
|
||||
- File names: kebab-case for components and pages.
|
||||
- CSS variables driven by SCSS maps define themes (light/dark) and accent colors.
|
||||
- TUI aesthetic: box-drawing characters, monospace font (**Hermit** / "Hurmit" via Nerd Fonts), `steps()` easing transitions, pixel-art SVG elements.
|
||||
- Headings and buttons carry no `>` prompt prefix.
|
||||
- Titles use proper capitalization: sentence case with capitalized proper nouns (e.g. "Admin dashboard", "Hibolia orders"), never ALL CAPS.
|
||||
|
||||
## Content Collections
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
<style lang="scss" scoped>
|
||||
.tui-frame {
|
||||
position: relative;
|
||||
margin: 15px;
|
||||
margin: var(--container-margin, 15px);
|
||||
background: var(--color-background-fore);
|
||||
box-shadow: 4px -4px 0px 0px var(--color-container-shadow);
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
margin-top: 60px;
|
||||
margin-bottom: 60px;
|
||||
}
|
||||
|
||||
span {
|
||||
|
||||
40
frontend/app/components/layouts/AdminLayout.vue
Normal file
40
frontend/app/components/layouts/AdminLayout.vue
Normal file
@@ -0,0 +1,40 @@
|
||||
<script setup lang="ts">
|
||||
import AdminSidebar from '~/components/parts/AdminSidebar.vue';
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="admin-shell">
|
||||
<AdminSidebar />
|
||||
<main class="admin-main">
|
||||
<slot />
|
||||
</main>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.admin-shell {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
z-index: 1000;
|
||||
display: flex;
|
||||
background: var(--color-background);
|
||||
}
|
||||
|
||||
.admin-main {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
overflow-y: auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.admin-main :slotted(*) {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 900px) {
|
||||
.admin-shell {
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
225
frontend/app/components/parts/AdminSidebar.vue
Normal file
225
frontend/app/components/parts/AdminSidebar.vue
Normal file
@@ -0,0 +1,225 @@
|
||||
<script setup lang="ts">
|
||||
const auth = useAuth()
|
||||
const route = useRoute()
|
||||
const localePath = useLocalePath()
|
||||
|
||||
const orderCount = useState<number | null>('admin-order-count', () => null)
|
||||
|
||||
const navItems = [
|
||||
{ key: 'dashboard', to: '/admin', label: 'admin.sidebar.nav_dashboard' },
|
||||
{ key: 'orders', to: '/admin/orders', label: 'admin.sidebar.nav_orders' }
|
||||
]
|
||||
|
||||
const isActive = (key: string) =>
|
||||
key === 'dashboard'
|
||||
? route.path === '/admin' || route.path === '/admin/'
|
||||
: route.path.startsWith('/admin/orders')
|
||||
|
||||
const onLogout = () => {
|
||||
auth.logout()
|
||||
navigateTo('/admin/login')
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<aside class="admin-sidebar">
|
||||
<div class="sidebar-head">
|
||||
<span class="sidebar-title">{{ $t('admin.sidebar.title') }}</span>
|
||||
</div>
|
||||
|
||||
<span class="sidebar-rule" aria-hidden="true">══════════════════</span>
|
||||
|
||||
<nav class="sidebar-nav">
|
||||
<NuxtLink
|
||||
v-for="item in navItems"
|
||||
:key="item.key"
|
||||
:to="item.to"
|
||||
class="nav-item"
|
||||
:class="{ 'nav-item-active': isActive(item.key) }"
|
||||
>
|
||||
<span class="nav-sep" aria-hidden="true">{{ item.key === 'dashboard' ? '▸' : '├' }}</span>
|
||||
<span class="nav-label">{{ $t(item.label) }}</span>
|
||||
<span v-if="item.key === 'orders' && orderCount !== null" class="nav-badge">[{{ orderCount }}]</span>
|
||||
</NuxtLink>
|
||||
</nav>
|
||||
|
||||
<div class="sidebar-bottom">
|
||||
<span class="sidebar-rule" aria-hidden="true">══════════════════</span>
|
||||
<NuxtLink :to="localePath('index')" class="nav-item nav-item-site">
|
||||
<span class="nav-sep" aria-hidden="true">←</span>
|
||||
<span class="nav-label">{{ $t('admin.sidebar.back_site') }}</span>
|
||||
</NuxtLink>
|
||||
<button class="sidebar-logout" @click="onLogout">>_ {{ $t('admin.dashboard.logout') }}</button>
|
||||
</div>
|
||||
</aside>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.admin-sidebar {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 220px;
|
||||
flex-shrink: 0;
|
||||
padding: 16px 12px;
|
||||
background: var(--color-background-fore);
|
||||
border-right: 1px solid var(--color-border-color);
|
||||
box-shadow: inset -2px 0 0 0 var(--color-container-shadow);
|
||||
}
|
||||
|
||||
.sidebar-head {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
gap: 8px;
|
||||
padding: 0 6px 8px;
|
||||
}
|
||||
|
||||
.sidebar-title {
|
||||
font-family: 'Hurmit', monospace;
|
||||
font-size: 1rem;
|
||||
letter-spacing: 2px;
|
||||
color: var(--color-text);
|
||||
}
|
||||
|
||||
.sidebar-rule {
|
||||
display: block;
|
||||
font-family: 'Hurmit', monospace;
|
||||
font-size: 8px;
|
||||
line-height: 1;
|
||||
color: var(--color-border-color);
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
margin: 4px 0 12px;
|
||||
}
|
||||
|
||||
.sidebar-nav {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 2px;
|
||||
}
|
||||
|
||||
.nav-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 6px 10px;
|
||||
font-family: 'Hurmit', monospace;
|
||||
font-size: 0.85rem;
|
||||
color: var(--color-text);
|
||||
text-decoration: none;
|
||||
text-shadow: none;
|
||||
border: 1px solid transparent;
|
||||
transition: all 120ms steps(3);
|
||||
|
||||
.nav-sep {
|
||||
color: var(--color-text);
|
||||
opacity: 0.35;
|
||||
font-size: 0.75rem;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: var(--color-hover);
|
||||
border-color: var(--color-border-color);
|
||||
|
||||
.nav-sep {
|
||||
color: var(--color-link);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.nav-item-active {
|
||||
color: var(--color-link);
|
||||
border-color: var(--color-link);
|
||||
|
||||
.nav-sep,
|
||||
.nav-badge {
|
||||
color: var(--color-link);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.nav-badge {
|
||||
margin-left: auto;
|
||||
font-size: 0.72rem;
|
||||
color: var(--color-link);
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
.sidebar-bottom {
|
||||
margin-top: auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 2px;
|
||||
}
|
||||
|
||||
.sidebar-logout {
|
||||
font-family: 'Hurmit', monospace;
|
||||
font-size: 0.85rem;
|
||||
color: var(--color-text);
|
||||
background: transparent;
|
||||
border: 1px solid var(--color-border-color);
|
||||
padding: 6px 14px;
|
||||
margin-top: 8px;
|
||||
cursor: pointer;
|
||||
text-align: left;
|
||||
transition: all 120ms steps(3);
|
||||
|
||||
&:hover {
|
||||
color: var(--color-link);
|
||||
border-color: var(--color-link);
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 900px) {
|
||||
.admin-sidebar {
|
||||
width: 100%;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
padding: 8px 12px;
|
||||
border-right: none;
|
||||
border-bottom: 1px solid var(--color-border-color);
|
||||
box-shadow: inset 0 -2px 0 0 var(--color-container-shadow);
|
||||
}
|
||||
|
||||
.sidebar-head {
|
||||
padding: 0;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.sidebar-rule {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.sidebar-nav {
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.sidebar-bottom {
|
||||
margin-top: 0;
|
||||
margin-left: auto;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.sidebar-logout {
|
||||
margin-top: 0;
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 600px) {
|
||||
.nav-item {
|
||||
font-size: 0.75rem;
|
||||
padding: 4px 8px;
|
||||
}
|
||||
|
||||
.sidebar-logout {
|
||||
font-size: 0.75rem;
|
||||
padding: 4px 10px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -89,6 +89,13 @@ onUnmounted(() => window.removeEventListener('scroll', onScroll));
|
||||
transform 0.3s cubic-bezier(0.4, 0, 0.2, 1),
|
||||
opacity 0.3s ease;
|
||||
|
||||
// Below 900px the full header is hidden, so keep the bar always shown.
|
||||
@media screen and (max-width: 900px) {
|
||||
transform: translateY(0);
|
||||
opacity: 1;
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
&.visible {
|
||||
transform: translateY(0);
|
||||
opacity: 1;
|
||||
|
||||
@@ -120,7 +120,7 @@ const preloadImages = (imageArray) => {
|
||||
<style lang="scss" scoped>
|
||||
.header {
|
||||
position: relative;
|
||||
margin-top: 30px;
|
||||
margin-top: 42px;
|
||||
user-select: none;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
@@ -129,6 +129,10 @@ const preloadImages = (imageArray) => {
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 900px) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.header-container {
|
||||
@@ -139,6 +143,12 @@ const preloadImages = (imageArray) => {
|
||||
margin-top: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
&.right {
|
||||
:deep(.site-options) {
|
||||
margin-top: 12px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.undertable-wrapper {
|
||||
@@ -153,16 +163,8 @@ const preloadImages = (imageArray) => {
|
||||
margin-top: -340px;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 900px) and (min-width: 600px) {
|
||||
margin-top: -240px;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 600px) {
|
||||
margin-top: -300px;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 480px) {
|
||||
margin-top: -340px;
|
||||
@media screen and (max-width: 900px) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import AdminLayout from '~/components/layouts/AdminLayout.vue';
|
||||
|
||||
definePageMeta({ middleware: 'admin-auth' });
|
||||
|
||||
useHead({
|
||||
@@ -10,34 +12,9 @@ const { getAuth } = useApi();
|
||||
const auth = useAuth();
|
||||
|
||||
const stats = ref<any>(null);
|
||||
const orders = ref<any[]>([]);
|
||||
const loading = ref(true);
|
||||
const errorMsg = ref('');
|
||||
|
||||
const COLOR_HEX: Record<string, string> = {
|
||||
red: '#d64545',
|
||||
gold: '#d4af37',
|
||||
silver: '#c0c0c0',
|
||||
orange: '#e0823c',
|
||||
yellow: '#e2cf3c',
|
||||
green: '#5fae4e',
|
||||
blue: '#4c8be0',
|
||||
purple: '#9b59d0',
|
||||
black: '#1a1a1a',
|
||||
white: '#f2f2f2',
|
||||
pink: '#e88fb3',
|
||||
turquoise: '#40c4b8',
|
||||
teal: '#17857c',
|
||||
navy: '#34549c',
|
||||
lavender: '#b98fe0',
|
||||
magenta: '#cf479f',
|
||||
lime: '#a8d14e',
|
||||
coral: '#ef8368'
|
||||
};
|
||||
|
||||
const orderSwatch = (order: any) =>
|
||||
order.color === 'custom' ? order.customColor : COLOR_HEX[order.color] || 'transparent';
|
||||
|
||||
const formatUptime = (seconds: number) => {
|
||||
const h = Math.floor(seconds / 3600);
|
||||
const m = Math.floor((seconds % 3600) / 60);
|
||||
@@ -68,28 +45,15 @@ const loadStats = async () => {
|
||||
}
|
||||
};
|
||||
|
||||
const loadOrders = async () => {
|
||||
try {
|
||||
orders.value = await getAuth('/hibolia/orders');
|
||||
} catch (e: any) {
|
||||
if (e?.status === 401) {
|
||||
redirectToLogin();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const formatDate = (value: string) => new Date(value).toLocaleString();
|
||||
|
||||
onMounted(async () => {
|
||||
const me = await auth.fetchMe();
|
||||
if (!me) {
|
||||
redirectToLogin();
|
||||
return;
|
||||
}
|
||||
await Promise.all([loadStats(), loadOrders()]);
|
||||
await loadStats();
|
||||
intervalId = setInterval(() => {
|
||||
loadStats();
|
||||
loadOrders();
|
||||
}, 30000);
|
||||
});
|
||||
|
||||
@@ -97,17 +61,12 @@ let intervalId: ReturnType<typeof setInterval> | null = null;
|
||||
onBeforeUnmount(() => {
|
||||
if (intervalId) clearInterval(intervalId);
|
||||
});
|
||||
|
||||
const onLogout = () => redirectToLogin();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="dash-screen">
|
||||
<AdminLayout>
|
||||
<Container class="dash-frame">
|
||||
<div class="dash-top">
|
||||
<h1 class="dash-title">> {{ $t('admin.dashboard.title') }}</h1>
|
||||
<button class="logout-btn" @click="onLogout">>_ {{ $t('admin.dashboard.logout') }}</button>
|
||||
</div>
|
||||
<h1 class="dash-title">{{ $t('admin.dashboard.title') }}</h1>
|
||||
|
||||
<p v-if="auth.user.value" class="dash-welcome">
|
||||
{{ $t('admin.dashboard.welcome') }} <span class="hl">{{ auth.user.value.username }}</span>
|
||||
@@ -117,6 +76,7 @@ const onLogout = () => redirectToLogin();
|
||||
<p v-if="loading" class="dash-loading blink">{{ $t('admin.dashboard.loading') }}</p>
|
||||
|
||||
<template v-if="stats && !loading">
|
||||
<section>
|
||||
<h2 class="dash-section">{{ $t('admin.dashboard.section_status') }}</h2>
|
||||
<div class="stat-grid">
|
||||
<div class="stat-card">
|
||||
@@ -144,91 +104,26 @@ const onLogout = () => redirectToLogin();
|
||||
<span class="stat-value">{{ stats.grid.totalCells }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h2 class="dash-section">{{ $t('admin.dashboard.section_orders') }} <span class="hl">[{{ orders.length }}]</span></h2>
|
||||
<p v-if="!orders.length" class="dash-loading">{{ $t('admin.dashboard.orders_empty') }}</p>
|
||||
<table v-else class="orders-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{{ $t('admin.dashboard.col_date') }}</th>
|
||||
<th>{{ $t('admin.dashboard.col_name') }}</th>
|
||||
<th>{{ $t('admin.dashboard.col_email') }}</th>
|
||||
<th>{{ $t('admin.dashboard.col_message') }}</th>
|
||||
<th>{{ $t('admin.dashboard.col_color') }}</th>
|
||||
<th>{{ $t('admin.dashboard.col_shipping') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="order in orders" :key="order._id">
|
||||
<td class="nowrap">{{ formatDate(order.createdAt) }}</td>
|
||||
<td>{{ order.name }} {{ order.surname }}</td>
|
||||
<td>{{ order.email }}</td>
|
||||
<td class="msg-cell">{{ order.message }}</td>
|
||||
<td>
|
||||
<span class="color-chip">
|
||||
<span class="swatch" :style="{ background: orderSwatch(order) }" aria-hidden="true"></span>
|
||||
{{ $t(`order.hibolia.colors.${order.color}`) }}<template v-if="order.color === 'custom'"> {{ order.customColor }}</template>
|
||||
</span>
|
||||
</td>
|
||||
<td class="msg-cell">{{ order.shipping }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</section>
|
||||
</template>
|
||||
</Container>
|
||||
</div>
|
||||
</AdminLayout>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.dash-screen {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
z-index: 1000;
|
||||
display: flex;
|
||||
background: var(--color-background);
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.dash-frame {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
--container-margin: 0;
|
||||
|
||||
:deep(.tui-inner) {
|
||||
flex: 1;
|
||||
width: 100%;
|
||||
max-width: 1400px;
|
||||
margin: 0 auto;
|
||||
padding-bottom: 96px;
|
||||
}
|
||||
}
|
||||
|
||||
.dash-top {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.dash-title {
|
||||
font-family: 'Hurmit', monospace;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.logout-btn {
|
||||
font-family: 'Hurmit', monospace;
|
||||
font-size: 0.85rem;
|
||||
color: var(--color-text);
|
||||
background: transparent;
|
||||
border: 1px solid var(--color-border-color);
|
||||
padding: 6px 14px;
|
||||
cursor: pointer;
|
||||
transition: all 120ms steps(3);
|
||||
|
||||
&:hover {
|
||||
color: var(--color-link);
|
||||
border-color: var(--color-link);
|
||||
}
|
||||
margin: 44px 0 32px;
|
||||
}
|
||||
|
||||
.dash-welcome {
|
||||
@@ -259,7 +154,7 @@ const onLogout = () => redirectToLogin();
|
||||
font-family: 'Hurmit', monospace;
|
||||
font-size: 1rem;
|
||||
color: var(--color-link);
|
||||
margin: 28px 0 12px;
|
||||
margin: 64px 0 18px;
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
gap: 16px;
|
||||
@@ -270,53 +165,6 @@ const onLogout = () => redirectToLogin();
|
||||
}
|
||||
}
|
||||
|
||||
.orders-table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
font-size: 0.85rem;
|
||||
|
||||
th,
|
||||
td {
|
||||
border: 1px solid var(--color-border-color);
|
||||
padding: 6px 10px;
|
||||
text-align: left;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
th {
|
||||
font-family: 'Hurmit', monospace;
|
||||
font-size: 0.72rem;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 1px;
|
||||
color: var(--color-link);
|
||||
background: var(--color-background-line);
|
||||
}
|
||||
}
|
||||
|
||||
.nowrap {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.msg-cell {
|
||||
white-space: pre-wrap;
|
||||
word-break: break-word;
|
||||
min-width: 200px;
|
||||
}
|
||||
|
||||
.color-chip {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.swatch {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
border: 1px solid var(--color-border-color);
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.stat-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
|
||||
|
||||
204
frontend/app/pages/admin/orders.vue
Normal file
204
frontend/app/pages/admin/orders.vue
Normal file
@@ -0,0 +1,204 @@
|
||||
<script setup lang="ts">
|
||||
import AdminLayout from '~/components/layouts/AdminLayout.vue';
|
||||
|
||||
definePageMeta({ middleware: 'admin-auth' });
|
||||
|
||||
useHead({
|
||||
title: 'Hibolia Orders — Admin',
|
||||
meta: [{ name: 'robots', content: 'noindex, nofollow', tagPriority: 'high' }]
|
||||
});
|
||||
|
||||
const { getAuth } = useApi();
|
||||
const auth = useAuth();
|
||||
|
||||
const orders = ref<any[]>([]);
|
||||
const loading = ref(true);
|
||||
|
||||
const orderCount = useState<number | null>('admin-order-count', () => null);
|
||||
watch(orders, (value) => {
|
||||
orderCount.value = value.length;
|
||||
});
|
||||
|
||||
const COLOR_HEX: Record<string, string> = {
|
||||
red: '#d64545',
|
||||
gold: '#d4af37',
|
||||
silver: '#c0c0c0',
|
||||
orange: '#e0823c',
|
||||
yellow: '#e2cf3c',
|
||||
green: '#5fae4e',
|
||||
blue: '#4c8be0',
|
||||
purple: '#9b59d0',
|
||||
black: '#1a1a1a',
|
||||
white: '#f2f2f2',
|
||||
pink: '#e88fb3',
|
||||
turquoise: '#40c4b8',
|
||||
teal: '#17857c',
|
||||
navy: '#34549c',
|
||||
lavender: '#b98fe0',
|
||||
magenta: '#cf479f',
|
||||
lime: '#a8d14e',
|
||||
coral: '#ef8368'
|
||||
};
|
||||
|
||||
const orderSwatch = (order: any) =>
|
||||
order.color === 'custom' ? order.customColor : COLOR_HEX[order.color] || 'transparent';
|
||||
|
||||
const redirectToLogin = () => {
|
||||
auth.logout();
|
||||
navigateTo('/admin/login');
|
||||
};
|
||||
|
||||
const loadOrders = async () => {
|
||||
try {
|
||||
orders.value = await getAuth('/hibolia/orders');
|
||||
} catch (e: any) {
|
||||
if (e?.status === 401) {
|
||||
redirectToLogin();
|
||||
}
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
const formatDate = (value: string) => new Date(value).toLocaleString();
|
||||
|
||||
onMounted(async () => {
|
||||
const me = await auth.fetchMe();
|
||||
if (!me) {
|
||||
redirectToLogin();
|
||||
return;
|
||||
}
|
||||
await loadOrders();
|
||||
intervalId = setInterval(() => {
|
||||
loadOrders();
|
||||
}, 30000);
|
||||
});
|
||||
|
||||
let intervalId: ReturnType<typeof setInterval> | null = null;
|
||||
onBeforeUnmount(() => {
|
||||
if (intervalId) clearInterval(intervalId);
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<AdminLayout>
|
||||
<Container class="dash-frame">
|
||||
<h1 class="dash-title">{{ $t('admin.dashboard.section_orders') }} <span class="hl">[{{ orders.length }}]</span></h1>
|
||||
|
||||
<p v-if="loading" class="dash-loading blink">{{ $t('admin.dashboard.loading') }}</p>
|
||||
|
||||
<p v-if="!loading && !orders.length" class="dash-loading">{{ $t('admin.dashboard.orders_empty') }}</p>
|
||||
<table v-else-if="!loading" class="orders-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{{ $t('admin.dashboard.col_date') }}</th>
|
||||
<th>{{ $t('admin.dashboard.col_name') }}</th>
|
||||
<th>{{ $t('admin.dashboard.col_email') }}</th>
|
||||
<th>{{ $t('admin.dashboard.col_message') }}</th>
|
||||
<th>{{ $t('admin.dashboard.col_color') }}</th>
|
||||
<th>{{ $t('admin.dashboard.col_shipping') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="order in orders" :key="order._id">
|
||||
<td class="nowrap">{{ formatDate(order.createdAt) }}</td>
|
||||
<td>{{ order.name }} {{ order.surname }}</td>
|
||||
<td>{{ order.email }}</td>
|
||||
<td class="msg-cell">{{ order.message }}</td>
|
||||
<td>
|
||||
<span class="color-chip">
|
||||
<span class="swatch" :style="{ background: orderSwatch(order) }" aria-hidden="true"></span>
|
||||
{{ $t(`order.hibolia.colors.${order.color}`) }}<template v-if="order.color === 'custom'"> {{ order.customColor }}</template>
|
||||
</span>
|
||||
</td>
|
||||
<td class="msg-cell">{{ order.shipping }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</Container>
|
||||
</AdminLayout>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.dash-frame {
|
||||
--container-margin: 0;
|
||||
|
||||
:deep(.tui-inner) {
|
||||
max-width: 1400px;
|
||||
margin: 0 auto;
|
||||
padding-bottom: 96px;
|
||||
}
|
||||
}
|
||||
|
||||
.dash-title {
|
||||
font-family: 'Hurmit', monospace;
|
||||
margin: 44px 0 32px;
|
||||
|
||||
.hl {
|
||||
color: var(--color-text);
|
||||
opacity: 0.6;
|
||||
}
|
||||
}
|
||||
|
||||
.dash-loading {
|
||||
font-family: 'Hurmit', monospace;
|
||||
color: var(--color-link);
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
.orders-table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
font-size: 0.85rem;
|
||||
|
||||
th,
|
||||
td {
|
||||
border: 1px solid var(--color-border-color);
|
||||
padding: 6px 10px;
|
||||
text-align: left;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
th {
|
||||
font-family: 'Hurmit', monospace;
|
||||
font-size: 0.72rem;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 1px;
|
||||
color: var(--color-link);
|
||||
background: var(--color-background-line);
|
||||
}
|
||||
}
|
||||
|
||||
.nowrap {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.msg-cell {
|
||||
white-space: pre-wrap;
|
||||
word-break: break-word;
|
||||
min-width: 200px;
|
||||
}
|
||||
|
||||
.color-chip {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.swatch {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
border: 1px solid var(--color-border-color);
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.blink {
|
||||
animation: blink 1s step-end infinite;
|
||||
}
|
||||
|
||||
@keyframes blink {
|
||||
0%, 50%, 100% { opacity: 1; }
|
||||
25%, 75% { opacity: 0; }
|
||||
}
|
||||
</style>
|
||||
@@ -146,20 +146,26 @@
|
||||
"error_invalid": "Accés denegat: credencials no vàlides.",
|
||||
"error_generic": "L'autenticació ha fallat. Torna-ho a provar més tard."
|
||||
},
|
||||
"sidebar": {
|
||||
"title": "ADMIN",
|
||||
"nav_dashboard": "panell",
|
||||
"nav_orders": "comandes",
|
||||
"back_site": "veure el lloc"
|
||||
},
|
||||
"dashboard": {
|
||||
"title": "TAULER D'ADMINISTRACIÓ",
|
||||
"title": "Tauler d'administració",
|
||||
"welcome": "sessió activa com a",
|
||||
"logout": "tancar sessió",
|
||||
"loading": "carregant dades del sistema...",
|
||||
"load_error": "No s'han pogut carregar les dades del tauler.",
|
||||
"section_status": "estat del sistema",
|
||||
"section_status": "Estat del sistema",
|
||||
"status": "estat",
|
||||
"mongo": "base de dades",
|
||||
"uptime": "temps actiu",
|
||||
"memory_rss": "memòria (rss)",
|
||||
"memory_heap": "heap usat",
|
||||
"total_cells": "cel·les pintades",
|
||||
"section_orders": "comandes hibolia",
|
||||
"section_orders": "Comandes hibolia",
|
||||
"orders_empty": "encara no hi ha comandes.",
|
||||
"col_date": "data",
|
||||
"col_name": "nom",
|
||||
|
||||
@@ -146,20 +146,26 @@
|
||||
"error_invalid": "Access denied: invalid credentials.",
|
||||
"error_generic": "Authentication failed. Try again later."
|
||||
},
|
||||
"sidebar": {
|
||||
"title": "ADMIN",
|
||||
"nav_dashboard": "dashboard",
|
||||
"nav_orders": "orders",
|
||||
"back_site": "view site"
|
||||
},
|
||||
"dashboard": {
|
||||
"title": "ADMIN DASHBOARD",
|
||||
"title": "Admin dashboard",
|
||||
"welcome": "session active as",
|
||||
"logout": "logout",
|
||||
"loading": "loading system data...",
|
||||
"load_error": "Could not load dashboard data.",
|
||||
"section_status": "system status",
|
||||
"section_status": "System status",
|
||||
"status": "status",
|
||||
"mongo": "database",
|
||||
"uptime": "uptime",
|
||||
"memory_rss": "memory (rss)",
|
||||
"memory_heap": "heap used",
|
||||
"total_cells": "cells painted",
|
||||
"section_orders": "hibolia orders",
|
||||
"section_orders": "Hibolia orders",
|
||||
"orders_empty": "no orders yet.",
|
||||
"col_date": "date",
|
||||
"col_name": "name",
|
||||
|
||||
@@ -146,20 +146,26 @@
|
||||
"error_invalid": "Acceso denegado: credenciales no válidas.",
|
||||
"error_generic": "La autenticación ha fallado. Inténtalo más tarde."
|
||||
},
|
||||
"sidebar": {
|
||||
"title": "ADMIN",
|
||||
"nav_dashboard": "panel",
|
||||
"nav_orders": "pedidos",
|
||||
"back_site": "ver el sitio"
|
||||
},
|
||||
"dashboard": {
|
||||
"title": "PANEL DE ADMINISTRACIÓN",
|
||||
"title": "Panel de administración",
|
||||
"welcome": "sesión activa como",
|
||||
"logout": "cerrar sesión",
|
||||
"loading": "cargando datos del sistema...",
|
||||
"load_error": "No se pudieron cargar los datos del panel.",
|
||||
"section_status": "estado del sistema",
|
||||
"section_status": "Estado del sistema",
|
||||
"status": "estado",
|
||||
"mongo": "base de datos",
|
||||
"uptime": "tiempo activo",
|
||||
"memory_rss": "memoria (rss)",
|
||||
"memory_heap": "heap usado",
|
||||
"total_cells": "células pintadas",
|
||||
"section_orders": "pedidos hibolia",
|
||||
"section_orders": "Pedidos hibolia",
|
||||
"orders_empty": "aún no hay pedidos.",
|
||||
"col_date": "fecha",
|
||||
"col_name": "nombre",
|
||||
|
||||
@@ -146,6 +146,12 @@
|
||||
"error_invalid": "访问被拒绝:凭据无效。",
|
||||
"error_generic": "验证失败,请稍后再试。"
|
||||
},
|
||||
"sidebar": {
|
||||
"title": "管理",
|
||||
"nav_dashboard": "面板",
|
||||
"nav_orders": "订单",
|
||||
"back_site": "访问网站"
|
||||
},
|
||||
"dashboard": {
|
||||
"title": "管理面板",
|
||||
"welcome": "当前会话用户",
|
||||
@@ -159,7 +165,7 @@
|
||||
"memory_rss": "内存 (rss)",
|
||||
"memory_heap": "已用堆内存",
|
||||
"total_cells": "已绘制像素",
|
||||
"section_orders": "hibolia 订单",
|
||||
"section_orders": "Hibolia 订单",
|
||||
"orders_empty": "暂无订单。",
|
||||
"col_date": "日期",
|
||||
"col_name": "姓名",
|
||||
|
||||
@@ -44,5 +44,5 @@ export default defineNuxtConfig({
|
||||
}
|
||||
},
|
||||
|
||||
modules: ['@nuxtjs/i18n', '@nuxt/content', '@nuxt/image']
|
||||
modules: ['@nuxtjs/i18n', '@nuxt/content', '@nuxt/image', '@nuxtjs/turnstile']
|
||||
})
|
||||
806
frontend/package-lock.json
generated
806
frontend/package-lock.json
generated
@@ -9,7 +9,9 @@
|
||||
"dependencies": {
|
||||
"@nuxt/content": "^3.12.0",
|
||||
"@nuxt/image": "^2.0.0",
|
||||
"@nuxt/scripts": "^1.3.9",
|
||||
"@nuxtjs/i18n": "10.2.3",
|
||||
"@nuxtjs/turnstile": "^1.1.3",
|
||||
"better-sqlite3": "^12.10.0",
|
||||
"nuxt": "^4.3.1",
|
||||
"sass": "^1.98.0",
|
||||
@@ -704,28 +706,31 @@
|
||||
"integrity": "sha512-/B8YJGPzaYq1NbsQmwgP8EZqg40NpTw4ZB3suuI0TplbxKHeK94jeaawLmVhCv+YwUnOpiWEz9U6SeThku/8JQ=="
|
||||
},
|
||||
"node_modules/@emnapi/core": {
|
||||
"version": "1.9.0",
|
||||
"resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.9.0.tgz",
|
||||
"integrity": "sha512-0DQ98G9ZQZOxfUcQn1waV2yS8aWdZ6kJMbYCJB3oUBecjWYO1fqJ+a1DRfPF3O5JEkwqwP1A9QEN/9mYm2Yd0w==",
|
||||
"version": "1.11.2",
|
||||
"resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.11.2.tgz",
|
||||
"integrity": "sha512-TC8MkTuZUtcTSiFeuC0ksCh9QIJ5+F21MvZ4Wn4ORfYaFJ/0dsiudv5tVkejgwZlwQ39jL9WWDe2lz8x0WglOA==",
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"@emnapi/wasi-threads": "1.2.0",
|
||||
"@emnapi/wasi-threads": "1.2.2",
|
||||
"tslib": "^2.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@emnapi/runtime": {
|
||||
"version": "1.9.0",
|
||||
"resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.9.0.tgz",
|
||||
"integrity": "sha512-QN75eB0IH2ywSpRpNddCRfQIhmJYBCJ1x5Lb3IscKAL8bMnVAKnRg8dCoXbHzVLLH7P38N2Z3mtulB7W0J0FKw==",
|
||||
"version": "1.11.2",
|
||||
"resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.11.2.tgz",
|
||||
"integrity": "sha512-kyOl3X0DuTiT1h2ft8r2fYO8JYtU9a9Xis/zBSiGArNaagCOWx90N1k2wxp18czFDH+OgcWGb5ZP/XMt3dcyPA==",
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"tslib": "^2.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@emnapi/wasi-threads": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.0.tgz",
|
||||
"integrity": "sha512-N10dEJNSsUx41Z6pZsXU8FjPjpBEplgH24sfkmITrBED1/U2Esum9F3lfLrMjKHHjmi557zQn7kR9R+XWXu5Rg==",
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.2.tgz",
|
||||
"integrity": "sha512-c95qOXkHdydNKhscBTebqEC1CVAZpyqOfVfBzQ1qgzyl3gfeldUjIggDbIZgDKsHLgnsM+igH7TJ/eAasaVuMA==",
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"tslib": "^2.4.0"
|
||||
@@ -2153,9 +2158,10 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@jridgewell/sourcemap-codec": {
|
||||
"version": "1.5.5",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz",
|
||||
"integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og=="
|
||||
"version": "1.6.0",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.6.0.tgz",
|
||||
"integrity": "sha512-T7jf+5zgsZHwNJ4lvQ7/aezbyk0nNX+zJVWpmHA7VYsEx7a7qr5Rg5IbtJFqkgze5Y2sruq1RUY8Q837Od7iFw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@jridgewell/trace-mapping": {
|
||||
"version": "0.3.31",
|
||||
@@ -2218,18 +2224,24 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@napi-rs/wasm-runtime": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.1.tgz",
|
||||
"integrity": "sha512-p64ah1M1ld8xjWv3qbvFwHiFVWrq1yFvV4f7w+mzaqiR4IlSgkqhcRdHwsGgomwzBH51sRY4NEowLxnaBjcW/A==",
|
||||
"version": "1.2.4",
|
||||
"resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.2.4.tgz",
|
||||
"integrity": "sha512-AJxoUD2/15ESHbvpcyjU274nsAPLuOtPHCk0vKJM5pj//Fg/B1FXNWjPnXTT9PymCYYiHo4zPj0ZomXBKhoy7g==",
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"@emnapi/core": "^1.7.1",
|
||||
"@emnapi/runtime": "^1.7.1",
|
||||
"@tybys/wasm-util": "^0.10.1"
|
||||
"@tybys/wasm-util": "^0.10.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^20.19.0 || ^22.13.0 || >=23.5.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/Brooooooklyn"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@emnapi/core": "^1.7.1 || ^2.0.0-alpha.4",
|
||||
"@emnapi/runtime": "^1.7.1 || ^2.0.0-alpha.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@nodelib/fs.scandir": {
|
||||
@@ -2597,6 +2609,568 @@
|
||||
"node": "^14.18.0 || >=16.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@nuxt/scripts": {
|
||||
"version": "1.3.9",
|
||||
"resolved": "https://registry.npmjs.org/@nuxt/scripts/-/scripts-1.3.9.tgz",
|
||||
"integrity": "sha512-6OIvXXZ736YHtF7qLueO0foxQvhLhhjJ4zifBEhxAV7ouxI/NStmLIz70pQiPdhr26/1JZqHgGVfC91vJZPZIg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@nuxt/devtools-kit": "^3.2.4",
|
||||
"@vueuse/core": "^14.3.0",
|
||||
"@vueuse/shared": "^14.3.0",
|
||||
"consola": "^3.4.2",
|
||||
"defu": "^6.1.7",
|
||||
"h3": "^1.15.11",
|
||||
"magic-string": "^1.0.0",
|
||||
"ofetch": "^1.5.1",
|
||||
"ohash": "^2.0.11",
|
||||
"oxc-parser": "^0.140.0",
|
||||
"oxc-walker": "^1.0.0",
|
||||
"pathe": "^2.0.3",
|
||||
"pkg-types": "^2.3.1",
|
||||
"sirv": "^3.0.2",
|
||||
"std-env": "^4.2.0",
|
||||
"ufo": "^1.6.4",
|
||||
"ultrahtml": "^1.7.0",
|
||||
"undici": "^6.27.0",
|
||||
"unplugin": "^3.3.0",
|
||||
"unstorage": "^1.17.5",
|
||||
"valibot": "^1.4.2"
|
||||
},
|
||||
"bin": {
|
||||
"nuxt-scripts": "bin/cli.mjs"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@googlemaps/markerclusterer": "^2.6.2",
|
||||
"@paypal/paypal-js": "^8.1.2 || ^9.0.0",
|
||||
"@speedcurve/lux": "^4.4.3",
|
||||
"@stripe/stripe-js": "^7.0.0 || ^8.0.0 || ^9.0.0",
|
||||
"@types/google.maps": "^3.58.1",
|
||||
"@types/vimeo__player": "^2.18.3",
|
||||
"@types/youtube": "^0.1.0",
|
||||
"@unhead/vue": "^2.0.3 || ^3.0.0",
|
||||
"posthog-js": "^1.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@googlemaps/markerclusterer": {
|
||||
"optional": true
|
||||
},
|
||||
"@paypal/paypal-js": {
|
||||
"optional": true
|
||||
},
|
||||
"@speedcurve/lux": {
|
||||
"optional": true
|
||||
},
|
||||
"@stripe/stripe-js": {
|
||||
"optional": true
|
||||
},
|
||||
"@types/google.maps": {
|
||||
"optional": true
|
||||
},
|
||||
"@types/vimeo__player": {
|
||||
"optional": true
|
||||
},
|
||||
"@types/youtube": {
|
||||
"optional": true
|
||||
},
|
||||
"@unhead/vue": {
|
||||
"optional": true
|
||||
},
|
||||
"posthog-js": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@nuxt/scripts/node_modules/@oxc-parser/binding-android-arm-eabi": {
|
||||
"version": "0.140.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxc-parser/binding-android-arm-eabi/-/binding-android-arm-eabi-0.140.0.tgz",
|
||||
"integrity": "sha512-ZfjDZ422mo7eo3b3VltqNsV9kmv1qt/sPEAMSl64iOSwhVfd0eIZ9LB79Mbs1xYXJnk7WSROwzBCKDIiVxPTvQ==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^20.19.0 || >=22.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@nuxt/scripts/node_modules/@oxc-parser/binding-android-arm64": {
|
||||
"version": "0.140.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxc-parser/binding-android-arm64/-/binding-android-arm64-0.140.0.tgz",
|
||||
"integrity": "sha512-Ia8jSvikUX6Sf+Ht+KOCUF/k1HpR0VlmqIYymubmWDebOEGtsyliHDR6JxsZ4IX3/c/GbrB1uh09aVGQv/LQmQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^20.19.0 || >=22.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@nuxt/scripts/node_modules/@oxc-parser/binding-darwin-arm64": {
|
||||
"version": "0.140.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxc-parser/binding-darwin-arm64/-/binding-darwin-arm64-0.140.0.tgz",
|
||||
"integrity": "sha512-G6VK0nK61pH0d0mBjUqSZbVxGqqO5uzeginLDQj+gOO6ObfJjXRwgkD/ol0w1INcnFeAb6YGGO7qc3ueGHaycQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^20.19.0 || >=22.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@nuxt/scripts/node_modules/@oxc-parser/binding-darwin-x64": {
|
||||
"version": "0.140.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxc-parser/binding-darwin-x64/-/binding-darwin-x64-0.140.0.tgz",
|
||||
"integrity": "sha512-HazBOuZzd2pO1C2uMmp8Gv7mhzMHqKSKDS1OZfcLEvpIcgA+48J92HEtNanVHDIzRD9PRPCV6aS6fkZIWOVl8Q==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^20.19.0 || >=22.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@nuxt/scripts/node_modules/@oxc-parser/binding-freebsd-x64": {
|
||||
"version": "0.140.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxc-parser/binding-freebsd-x64/-/binding-freebsd-x64-0.140.0.tgz",
|
||||
"integrity": "sha512-9hSUU+HmTUyOe4JzMHxNGgLWNY7rrO+6ShicZwImNJacEAACDMIkuEQQkvXSL+WJN50jaNtLYJv8s4OcBdpyUQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"freebsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^20.19.0 || >=22.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@nuxt/scripts/node_modules/@oxc-parser/binding-linux-arm-gnueabihf": {
|
||||
"version": "0.140.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-0.140.0.tgz",
|
||||
"integrity": "sha512-RAEuQsYtS0KcDFqN0ABTjyyNlokS91JeuDuoW9tEbG0JTbRNXnpQUdbYc/16JoA6Z/2ALbNrE3KmxtqDiuIjCQ==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^20.19.0 || >=22.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@nuxt/scripts/node_modules/@oxc-parser/binding-linux-arm-musleabihf": {
|
||||
"version": "0.140.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-arm-musleabihf/-/binding-linux-arm-musleabihf-0.140.0.tgz",
|
||||
"integrity": "sha512-c4CkHvPvqfojouredJ0w3e6+jiBq0SbFyhH61kr/zPb/7XsaYTNKQ54vmlSsopfdQbNDX40ZeK9Abs2Qet6wcw==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^20.19.0 || >=22.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@nuxt/scripts/node_modules/@oxc-parser/binding-linux-arm64-gnu": {
|
||||
"version": "0.140.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-0.140.0.tgz",
|
||||
"integrity": "sha512-yrjmLj8ixPB25yqvPGr28meGjb+keed7m1GqqY/0uqkhZIoT4t9zmfwUgFEtC33C7dtE+UQ7TU0IaVxf97SWJg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"libc": [
|
||||
"glibc"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^20.19.0 || >=22.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@nuxt/scripts/node_modules/@oxc-parser/binding-linux-arm64-musl": {
|
||||
"version": "0.140.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-arm64-musl/-/binding-linux-arm64-musl-0.140.0.tgz",
|
||||
"integrity": "sha512-ggGMQTN8Agwxp2WiLMpdY671dt0qTDJWiWlJeig3HnUwTnerRl0J2JdGVghWBeDcss2D9S2V2Js6dZHEiVabVA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"libc": [
|
||||
"musl"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^20.19.0 || >=22.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@nuxt/scripts/node_modules/@oxc-parser/binding-linux-ppc64-gnu": {
|
||||
"version": "0.140.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-0.140.0.tgz",
|
||||
"integrity": "sha512-IgTs8xYAFgAUGNmR65tIqjlJ8vKgrfXzC515e9goSdfMyKQV4aJpd2pUUudU4u51G64H0/DSEJEXKOraxm9ZCA==",
|
||||
"cpu": [
|
||||
"ppc64"
|
||||
],
|
||||
"libc": [
|
||||
"glibc"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^20.19.0 || >=22.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@nuxt/scripts/node_modules/@oxc-parser/binding-linux-riscv64-gnu": {
|
||||
"version": "0.140.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-riscv64-gnu/-/binding-linux-riscv64-gnu-0.140.0.tgz",
|
||||
"integrity": "sha512-A1x+PMWZmSGaFVOx2YeNTFau8uD+QO14/vLP4GrcuvUPs3+nBkUOjy9Lus86ftHsDojjYMbvBelmKc3F7Rv08g==",
|
||||
"cpu": [
|
||||
"riscv64"
|
||||
],
|
||||
"libc": [
|
||||
"glibc"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^20.19.0 || >=22.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@nuxt/scripts/node_modules/@oxc-parser/binding-linux-riscv64-musl": {
|
||||
"version": "0.140.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-riscv64-musl/-/binding-linux-riscv64-musl-0.140.0.tgz",
|
||||
"integrity": "sha512-zBqpfRo2myWPrPo5xUjeZqlnPXPXsX8BcWtWff66/eGRQdbPjhzPgXa/F+AtxT2afUViPxbuDlwscMKzQ5tg+g==",
|
||||
"cpu": [
|
||||
"riscv64"
|
||||
],
|
||||
"libc": [
|
||||
"musl"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^20.19.0 || >=22.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@nuxt/scripts/node_modules/@oxc-parser/binding-linux-s390x-gnu": {
|
||||
"version": "0.140.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-0.140.0.tgz",
|
||||
"integrity": "sha512-2M1DPm/8w9I//YzFlFC9qXw+r2tJFh5CYwRlYTq2vUJQS7qoQftEDeCZ8EnN7KHtvSiXvYj8mZI5pR7DpXmcEw==",
|
||||
"cpu": [
|
||||
"s390x"
|
||||
],
|
||||
"libc": [
|
||||
"glibc"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^20.19.0 || >=22.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@nuxt/scripts/node_modules/@oxc-parser/binding-linux-x64-gnu": {
|
||||
"version": "0.140.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-x64-gnu/-/binding-linux-x64-gnu-0.140.0.tgz",
|
||||
"integrity": "sha512-8aRDbZ/U/jO8N7go1MO72jtbpb4uswV8d7vOkMvt/BPgZiyEYvl1VIWK4ESxZZhnJ4tqwVldgX7dNiP/eB1Jdg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"libc": [
|
||||
"glibc"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^20.19.0 || >=22.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@nuxt/scripts/node_modules/@oxc-parser/binding-linux-x64-musl": {
|
||||
"version": "0.140.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-x64-musl/-/binding-linux-x64-musl-0.140.0.tgz",
|
||||
"integrity": "sha512-xRqpeI8U2sQQS1W5BMWRyMTxtagkuLG2dEWruet5lFsWHTvBth11/TpSaJatHdqVVwHN0q3uuoS9zRsGinq8hg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"libc": [
|
||||
"musl"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^20.19.0 || >=22.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@nuxt/scripts/node_modules/@oxc-parser/binding-openharmony-arm64": {
|
||||
"version": "0.140.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxc-parser/binding-openharmony-arm64/-/binding-openharmony-arm64-0.140.0.tgz",
|
||||
"integrity": "sha512-GbGRe26MqAKciFRvXeHNQJ6VAHYs9R4miP89sEAncysM3n+f4lnyLWgsa9kklJNpfnxdq2yRoNYHFqwBckVimw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"openharmony"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^20.19.0 || >=22.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@nuxt/scripts/node_modules/@oxc-parser/binding-wasm32-wasi": {
|
||||
"version": "0.140.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxc-parser/binding-wasm32-wasi/-/binding-wasm32-wasi-0.140.0.tgz",
|
||||
"integrity": "sha512-vFiC1hqys+hkX1GnQkIoiTQJNiUm43Z0lO35ETKXTw0YtpW7+cN58YRRXFAQQ+TgpkIi3lrhcxdlnqz+Oi3ptQ==",
|
||||
"cpu": [
|
||||
"wasm32"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"@emnapi/core": "1.11.2",
|
||||
"@emnapi/runtime": "1.11.2",
|
||||
"@napi-rs/wasm-runtime": "^1.1.6"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^20.19.0 || >=22.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@nuxt/scripts/node_modules/@oxc-parser/binding-win32-arm64-msvc": {
|
||||
"version": "0.140.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxc-parser/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-0.140.0.tgz",
|
||||
"integrity": "sha512-fGSQldwEYKhM+H8uLt76Op8hh5+FYaR6lvvQ1Txw3Mhn86DyQXLcI0fi1EkFlTK7F+46OCk/j0AJMzZQm6g5Xg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^20.19.0 || >=22.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@nuxt/scripts/node_modules/@oxc-parser/binding-win32-ia32-msvc": {
|
||||
"version": "0.140.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxc-parser/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-0.140.0.tgz",
|
||||
"integrity": "sha512-sDS2Bai+g3ZWYwfZqmosiSuFDBcVnZ3Ta6pszzsiJoLMqsJEWKcxXXbGa7b7yXr++W2lQNPb3ZRJ8czseqL7RA==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^20.19.0 || >=22.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@nuxt/scripts/node_modules/@oxc-parser/binding-win32-x64-msvc": {
|
||||
"version": "0.140.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxc-parser/binding-win32-x64-msvc/-/binding-win32-x64-msvc-0.140.0.tgz",
|
||||
"integrity": "sha512-kHbE1zWyb5OQgJA6/5P4WjiuB01sYdQwtZnSSyE58FQEXDAMnyeeq4vj7KgN75i5SlBzOs8A5MrtlD3gOlDKqQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^20.19.0 || >=22.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@nuxt/scripts/node_modules/@oxc-project/types": {
|
||||
"version": "0.140.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.140.0.tgz",
|
||||
"integrity": "sha512-h5LUOzGArYemnW1NMz/DuuQhBi96J6JL2Bk8zE4kvqxB5Sg3jxmCiH4uyOWHDkiKSt5vWlG4FIwCR/DbstcNRQ==",
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/Boshen"
|
||||
}
|
||||
},
|
||||
"node_modules/@nuxt/scripts/node_modules/magic-string": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-1.4.1.tgz",
|
||||
"integrity": "sha512-8lyCu36ErXR0J9uaGKlKQoiLZKmtI63YGLE8G2o9jyRPdr4X47LusSOwgOJOzcVtp81fTAAjxR7BwKz682Jhow==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@jridgewell/sourcemap-codec": "^1.6.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@nuxt/scripts/node_modules/oxc-parser": {
|
||||
"version": "0.140.0",
|
||||
"resolved": "https://registry.npmjs.org/oxc-parser/-/oxc-parser-0.140.0.tgz",
|
||||
"integrity": "sha512-h6QFWd6lBMfjESqgQ27GjzrSDb0qbznp7VDQqp2zvgsrWut4vcchyMIzOVXvGQ2GMZgKw9RWrFNWv9WqGL0p7Q==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@oxc-project/types": "^0.140.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^20.19.0 || >=22.12.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/Boshen"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@oxc-parser/binding-android-arm-eabi": "0.140.0",
|
||||
"@oxc-parser/binding-android-arm64": "0.140.0",
|
||||
"@oxc-parser/binding-darwin-arm64": "0.140.0",
|
||||
"@oxc-parser/binding-darwin-x64": "0.140.0",
|
||||
"@oxc-parser/binding-freebsd-x64": "0.140.0",
|
||||
"@oxc-parser/binding-linux-arm-gnueabihf": "0.140.0",
|
||||
"@oxc-parser/binding-linux-arm-musleabihf": "0.140.0",
|
||||
"@oxc-parser/binding-linux-arm64-gnu": "0.140.0",
|
||||
"@oxc-parser/binding-linux-arm64-musl": "0.140.0",
|
||||
"@oxc-parser/binding-linux-ppc64-gnu": "0.140.0",
|
||||
"@oxc-parser/binding-linux-riscv64-gnu": "0.140.0",
|
||||
"@oxc-parser/binding-linux-riscv64-musl": "0.140.0",
|
||||
"@oxc-parser/binding-linux-s390x-gnu": "0.140.0",
|
||||
"@oxc-parser/binding-linux-x64-gnu": "0.140.0",
|
||||
"@oxc-parser/binding-linux-x64-musl": "0.140.0",
|
||||
"@oxc-parser/binding-openharmony-arm64": "0.140.0",
|
||||
"@oxc-parser/binding-wasm32-wasi": "0.140.0",
|
||||
"@oxc-parser/binding-win32-arm64-msvc": "0.140.0",
|
||||
"@oxc-parser/binding-win32-ia32-msvc": "0.140.0",
|
||||
"@oxc-parser/binding-win32-x64-msvc": "0.140.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@nuxt/scripts/node_modules/oxc-walker": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/oxc-walker/-/oxc-walker-1.1.1.tgz",
|
||||
"integrity": "sha512-Hwd7dq28zu/Er99+bpWp16CGwFrhyalJh0W3JOB7XpPvgWo3MqMi2ksWGKuzzA9zt50mJ2pIUwR5lpAdZ9ACNQ==",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"@oxc-project/types": ">=0.98.0",
|
||||
"oxc-parser": ">=0.98.0",
|
||||
"rolldown": ">=1.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@oxc-project/types": {
|
||||
"optional": true
|
||||
},
|
||||
"oxc-parser": {
|
||||
"optional": true
|
||||
},
|
||||
"rolldown": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@nuxt/scripts/node_modules/undici": {
|
||||
"version": "6.28.1",
|
||||
"resolved": "https://registry.npmjs.org/undici/-/undici-6.28.1.tgz",
|
||||
"integrity": "sha512-zWpdTVD54H48CIybL0rWQ3ukpb9d23wM7eH5RtfdmeP70cWHNjtfo7P4vZX+5CoDcO53J4Pu5uXp7lNfjc6DRA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18.17"
|
||||
}
|
||||
},
|
||||
"node_modules/@nuxt/scripts/node_modules/unplugin": {
|
||||
"version": "3.4.0",
|
||||
"resolved": "https://registry.npmjs.org/unplugin/-/unplugin-3.4.0.tgz",
|
||||
"integrity": "sha512-9skdIFlCsPdFV7wUfZxNsFInlW+7nJmGu2gkTu0OUhF56aXGsHab9x52/QhdJ4lC7ZDPWTxbiC4ANqVlsuaW3w==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@jridgewell/remapping": "^2.3.5",
|
||||
"picomatch": "^4.0.7",
|
||||
"webpack-virtual-modules": "^0.6.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^20.19.0 || >=22.12.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@farmfe/core": "*",
|
||||
"@rsbuild/core": "*",
|
||||
"@rspack/core": "*",
|
||||
"bun-types-no-globals": "*",
|
||||
"esbuild": "*",
|
||||
"rolldown": "*",
|
||||
"rollup": "*",
|
||||
"unloader": "*",
|
||||
"vite": "*",
|
||||
"webpack": "*"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@farmfe/core": {
|
||||
"optional": true
|
||||
},
|
||||
"@rsbuild/core": {
|
||||
"optional": true
|
||||
},
|
||||
"@rspack/core": {
|
||||
"optional": true
|
||||
},
|
||||
"bun-types-no-globals": {
|
||||
"optional": true
|
||||
},
|
||||
"esbuild": {
|
||||
"optional": true
|
||||
},
|
||||
"rolldown": {
|
||||
"optional": true
|
||||
},
|
||||
"rollup": {
|
||||
"optional": true
|
||||
},
|
||||
"unloader": {
|
||||
"optional": true
|
||||
},
|
||||
"vite": {
|
||||
"optional": true
|
||||
},
|
||||
"webpack": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@nuxt/telemetry": {
|
||||
"version": "2.7.0",
|
||||
"resolved": "https://registry.npmjs.org/@nuxt/telemetry/-/telemetry-2.7.0.tgz",
|
||||
@@ -3015,6 +3589,53 @@
|
||||
"@types/hast": "^3.0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@nuxtjs/turnstile": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@nuxtjs/turnstile/-/turnstile-1.1.3.tgz",
|
||||
"integrity": "sha512-NKiRHvdCuuWz85VHWzhofPXxHFq6y2eOHXQPsrRJhLnEZ/YBvGt6beOxI0M50rHKMEmdYjM/30QomyzNLIBz4w==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@nuxt/kit": "^3.16.0",
|
||||
"@types/cloudflare-turnstile": "0.2.2",
|
||||
"defu": "^6.1.4",
|
||||
"pathe": "^2.0.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@nuxt/scripts": "^0.11.0 || ^0.12.0 || ^0.13.0 || ^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@nuxtjs/turnstile/node_modules/@nuxt/kit": {
|
||||
"version": "3.21.11",
|
||||
"resolved": "https://registry.npmjs.org/@nuxt/kit/-/kit-3.21.11.tgz",
|
||||
"integrity": "sha512-0Xi3tgwN77w43Q8GCPIrvWmF1J7Peehkts44E0uKNIml9lB8WoUn8YxyUjxBv47XtVR86NWoWALAT+/IEMHJEA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"c12": "^3.3.4",
|
||||
"consola": "^3.4.2",
|
||||
"defu": "^6.1.7",
|
||||
"destr": "^2.0.5",
|
||||
"errx": "^0.1.2",
|
||||
"exsolve": "^1.1.1",
|
||||
"ignore": "^7.0.6",
|
||||
"jiti": "^2.7.0",
|
||||
"klona": "^2.0.6",
|
||||
"knitwork": "^1.3.0",
|
||||
"mlly": "^1.8.2",
|
||||
"ohash": "^2.0.11",
|
||||
"pathe": "^2.0.3",
|
||||
"pkg-types": "^2.3.1",
|
||||
"rc9": "^3.0.1",
|
||||
"scule": "^1.3.0",
|
||||
"semver": "^7.8.5",
|
||||
"tinyglobby": "^0.2.17",
|
||||
"ufo": "^1.6.4",
|
||||
"unctx": "^2.5.0",
|
||||
"untyped": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@one-ini/wasm": {
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@one-ini/wasm/-/wasm-0.1.1.tgz",
|
||||
@@ -5250,9 +5871,10 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@tybys/wasm-util": {
|
||||
"version": "0.10.1",
|
||||
"resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.1.tgz",
|
||||
"integrity": "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==",
|
||||
"version": "0.10.4",
|
||||
"resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.4.tgz",
|
||||
"integrity": "sha512-W3c4gRigFS0T/Ma4qIYF3GDAc5AQdHb1yL5znJT1Zv1YaD9Kitx656wBjvr19qbiosmZT8lWDM5BEMynUqX65A==",
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"tslib": "^2.4.0"
|
||||
@@ -5276,6 +5898,12 @@
|
||||
"assertion-error": "^2.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/cloudflare-turnstile": {
|
||||
"version": "0.2.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/cloudflare-turnstile/-/cloudflare-turnstile-0.2.2.tgz",
|
||||
"integrity": "sha512-3Yf7b1Glci+V2bFWwWBbZkRgTuegp7RDgNTOG4U0UNPB9RV4AWvwqg2/qqLff8G+SwKFNXoXvTkqaRBZrAFdKA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/debug": {
|
||||
"version": "4.1.12",
|
||||
"resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz",
|
||||
@@ -5387,6 +6015,12 @@
|
||||
"integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/web-bluetooth": {
|
||||
"version": "0.0.21",
|
||||
"resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.21.tgz",
|
||||
"integrity": "sha512-oIQLCGWtcFZy2JW77j9k8nHzAOpqMHLQejDA48XXMWH6tjCQHz5RCFz1bzsmROyL6PUm+LLnUiI4BCn221inxA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/webxr": {
|
||||
"version": "0.5.24",
|
||||
"resolved": "https://registry.npmjs.org/@types/webxr/-/webxr-0.5.24.tgz",
|
||||
@@ -6001,6 +6635,44 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@vueuse/core": {
|
||||
"version": "14.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@vueuse/core/-/core-14.4.0.tgz",
|
||||
"integrity": "sha512-X4WHz1HlCzCBoYXesUkifzzWBAcZgXG8Fi5iNPQg/epdzOB3gu8Fawj3hvuwYR1nGcXGnvxwYYcUC/71++svtQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/web-bluetooth": "^0.0.21",
|
||||
"@vueuse/metadata": "14.4.0",
|
||||
"@vueuse/shared": "14.4.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/antfu"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"vue": "^3.5.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@vueuse/metadata": {
|
||||
"version": "14.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-14.4.0.tgz",
|
||||
"integrity": "sha512-swx/255R6JyHZFJhx845iz5CRWDZdCfvkZOpACWc5+c5WHcG24mv8gUT1WIdFQaHt6dq79rvILd9QnCWiyVm9g==",
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/antfu"
|
||||
}
|
||||
},
|
||||
"node_modules/@vueuse/shared": {
|
||||
"version": "14.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-14.4.0.tgz",
|
||||
"integrity": "sha512-JRgY90Sz8DDtPMsaDflvPMp9xYk69JZAmbuDvAquUVXKr2gEjqtzGNTTthLfckH0BzBqvnu31gb4a8TGLRe79g==",
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/antfu"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"vue": "^3.5.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@webcontainer/env": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@webcontainer/env/-/env-1.1.1.tgz",
|
||||
@@ -7144,9 +7816,10 @@
|
||||
"integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg=="
|
||||
},
|
||||
"node_modules/cookie-es": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/cookie-es/-/cookie-es-1.2.2.tgz",
|
||||
"integrity": "sha512-+W7VmiVINB+ywl1HGXJXmrqkOhpKrIiVZV6tQuV54ZyQC7MMuBt81Vc336GMLoHBq5hV/F9eXgt5Mnx0Rha5Fg=="
|
||||
"version": "1.2.3",
|
||||
"resolved": "https://registry.npmjs.org/cookie-es/-/cookie-es-1.2.3.tgz",
|
||||
"integrity": "sha512-lXVyvUvrNXblMqzIRrxHb57UUVmqsSWlxqt3XIjCkUP0wDAf6uicO6KMbEgYrMNtEvWgWHwe42CKxPu9MYAnWw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/core-util-is": {
|
||||
"version": "1.0.3",
|
||||
@@ -8045,9 +8718,10 @@
|
||||
}
|
||||
},
|
||||
"node_modules/errx": {
|
||||
"version": "0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/errx/-/errx-0.1.0.tgz",
|
||||
"integrity": "sha512-fZmsRiDNv07K6s2KkKFTiD2aIvECa7++PKyD5NC32tpRw46qZA3sOz+aM+/V9V0GDHxVTKLziveV4JhzBHDp9Q=="
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/errx/-/errx-0.1.2.tgz",
|
||||
"integrity": "sha512-chfpPHmCerdo/rXr/nNvPZRkV4WwDRwzwnsJ0Uzz3tVi8Z41tDctRjduYy1138ii77AFlts1qvWtX3g/Acg91Q==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/es-define-property": {
|
||||
"version": "1.0.1",
|
||||
@@ -8462,9 +9136,10 @@
|
||||
}
|
||||
},
|
||||
"node_modules/exsolve": {
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/exsolve/-/exsolve-1.0.8.tgz",
|
||||
"integrity": "sha512-LmDxfWXwcTArk8fUEnOfSZpHOJ6zOMUJKOtFLFqJLoKJetuQG874Uc7/Kki7zFLzYybmZhp1M7+98pfMqeX8yA=="
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/exsolve/-/exsolve-1.1.1.tgz",
|
||||
"integrity": "sha512-9U/jZUgjnSGyntRr6y5Muu1MJcwFl6kPu7k8qLF0IMNfLqvw0NZ4nnVDq0RVoZ0RvCyumib4Ez3KYrVfilrw+g==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/extend": {
|
||||
"version": "3.0.2",
|
||||
@@ -8950,13 +9625,14 @@
|
||||
}
|
||||
},
|
||||
"node_modules/h3": {
|
||||
"version": "1.15.8",
|
||||
"resolved": "https://registry.npmjs.org/h3/-/h3-1.15.8.tgz",
|
||||
"integrity": "sha512-iOH6Vl8mGd9nNfu9C0IZ+GuOAfJHcyf3VriQxWaSWIB76Fg4BnFuk4cxBxjmQSSxJS664+pgjP6e7VBnUzFfcg==",
|
||||
"version": "1.15.11",
|
||||
"resolved": "https://registry.npmjs.org/h3/-/h3-1.15.11.tgz",
|
||||
"integrity": "sha512-L3THSe2MPeBwgIZVSH5zLdBBU90TOxarvhK9d04IDY2AmVS8j2Jz2LIWtwsGOU3lu2I5jCN7FNvVfY2+XyF+mg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"cookie-es": "^1.2.2",
|
||||
"cookie-es": "^1.2.3",
|
||||
"crossws": "^0.3.5",
|
||||
"defu": "^6.1.4",
|
||||
"defu": "^6.1.6",
|
||||
"destr": "^2.0.5",
|
||||
"iron-webcrypto": "^1.2.1",
|
||||
"node-mock-http": "^1.0.4",
|
||||
@@ -9496,9 +10172,10 @@
|
||||
]
|
||||
},
|
||||
"node_modules/ignore": {
|
||||
"version": "7.0.5",
|
||||
"resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz",
|
||||
"integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==",
|
||||
"version": "7.0.9",
|
||||
"resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.9.tgz",
|
||||
"integrity": "sha512-brTTsvFRt5C1gGHtPst/281UjPD5t9fBqbgoMPlVWy11ZLTPfu7HxK4ZYqO9H7o/yC9rSTCI85EaQ4OoY12qYw==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 4"
|
||||
}
|
||||
@@ -14282,9 +14959,9 @@
|
||||
"integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="
|
||||
},
|
||||
"node_modules/picomatch": {
|
||||
"version": "4.0.4",
|
||||
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz",
|
||||
"integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==",
|
||||
"version": "4.0.7",
|
||||
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.7.tgz",
|
||||
"integrity": "sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
@@ -15665,9 +16342,9 @@
|
||||
"integrity": "sha512-6FtHJEvt+pVMIB9IBY+IcCJ6Z5f1iQnytgyfKMhDKgmzYG+TeH/wx1y3l27rshSbLiSanrR9ffZDrEsmjlQF2g=="
|
||||
},
|
||||
"node_modules/semver": {
|
||||
"version": "7.8.3",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.8.3.tgz",
|
||||
"integrity": "sha512-wnilbGyMxzbY7dNOl7jpKbLSjcfeweJWU5j4+u5qW+6/wuGD9KzIGOyZnQVSBM9E7DtWaaH3CyHkppYrKYoxwg==",
|
||||
"version": "7.8.5",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz",
|
||||
"integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==",
|
||||
"license": "ISC",
|
||||
"bin": {
|
||||
"semver": "bin/semver.js"
|
||||
@@ -16255,9 +16932,10 @@
|
||||
}
|
||||
},
|
||||
"node_modules/std-env": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/std-env/-/std-env-4.0.0.tgz",
|
||||
"integrity": "sha512-zUMPtQ/HBY3/50VbpkupYHbRroTRZJPRLvreamgErJVys0ceuzMkD44J/QjqhHjOzK42GQ3QZIeFG1OYfOtKqQ=="
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/std-env/-/std-env-4.2.0.tgz",
|
||||
"integrity": "sha512-oCUKSupKTHX53EyjDtuZQ64pjLJ6yYCtpmEw0goYxtjG9KpbRe8KAsl2tBUGU9DyMcJ0RwJ8GqJAFzMXcXW1Rw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/stop-iteration-iterator": {
|
||||
"version": "1.1.0",
|
||||
@@ -16911,9 +17589,10 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/ultrahtml": {
|
||||
"version": "1.6.0",
|
||||
"resolved": "https://registry.npmjs.org/ultrahtml/-/ultrahtml-1.6.0.tgz",
|
||||
"integrity": "sha512-R9fBn90VTJrqqLDwyMph+HGne8eqY1iPfYhPzZrvKpIfwkWZbcYlfpsb8B9dTvBfpy1/hqAD7Wi8EKfP9e8zdw=="
|
||||
"version": "1.7.0",
|
||||
"resolved": "https://registry.npmjs.org/ultrahtml/-/ultrahtml-1.7.0.tgz",
|
||||
"integrity": "sha512-2xRd0VHoAQE4M+vF/DvFFB7pUV0ZxTW1TLi7lHQWnF/Sb5TPeEUV/l+hxcNnGO00ZXGnR0voCMmYRKQf+rvJ2g==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/uncrypto": {
|
||||
"version": "0.1.3",
|
||||
@@ -17275,15 +17954,16 @@
|
||||
}
|
||||
},
|
||||
"node_modules/unstorage": {
|
||||
"version": "1.17.4",
|
||||
"resolved": "https://registry.npmjs.org/unstorage/-/unstorage-1.17.4.tgz",
|
||||
"integrity": "sha512-fHK0yNg38tBiJKp/Vgsq4j0JEsCmgqH58HAn707S7zGkArbZsVr/CwINoi+nh3h98BRCwKvx1K3Xg9u3VV83sw==",
|
||||
"version": "1.17.5",
|
||||
"resolved": "https://registry.npmjs.org/unstorage/-/unstorage-1.17.5.tgz",
|
||||
"integrity": "sha512-0i3iqvRfx29hkNntHyQvJTpf5W9dQ9ZadSoRU8+xVlhVtT7jAX57fazYO9EHvcRCfBCyi5YRya7XCDOsbTgkPg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"anymatch": "^3.1.3",
|
||||
"chokidar": "^5.0.0",
|
||||
"destr": "^2.0.5",
|
||||
"h3": "^1.15.5",
|
||||
"lru-cache": "^11.2.0",
|
||||
"h3": "^1.15.10",
|
||||
"lru-cache": "^11.2.7",
|
||||
"node-fetch-native": "^1.6.7",
|
||||
"ofetch": "^1.5.1",
|
||||
"ufo": "^1.6.3"
|
||||
@@ -17471,6 +18151,20 @@
|
||||
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
|
||||
},
|
||||
"node_modules/valibot": {
|
||||
"version": "1.5.0",
|
||||
"resolved": "https://registry.npmjs.org/valibot/-/valibot-1.5.0.tgz",
|
||||
"integrity": "sha512-nil6AkP2TChWL43Z5uJ6GTxX01CUA+g8LWUM+N/rB9NBbkUMaUsi9PUNzlUPgoKASgmx9f7eGOYpJ04/fSa6FQ==",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"typescript": ">=5"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"typescript": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/vfile": {
|
||||
"version": "6.0.3",
|
||||
"resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz",
|
||||
|
||||
@@ -14,7 +14,9 @@
|
||||
"dependencies": {
|
||||
"@nuxt/content": "^3.12.0",
|
||||
"@nuxt/image": "^2.0.0",
|
||||
"@nuxt/scripts": "^1.3.9",
|
||||
"@nuxtjs/i18n": "10.2.3",
|
||||
"@nuxtjs/turnstile": "^1.1.3",
|
||||
"better-sqlite3": "^12.10.0",
|
||||
"nuxt": "^4.3.1",
|
||||
"sass": "^1.98.0",
|
||||
|
||||
Reference in New Issue
Block a user