feat(home): update and fix home page

feat(campaigns): add campaigns page

chore: add oxlint linter on top of eslint

refactor(pocketbase): rework typing of Pocketbase store
This commit is contained in:
Lucien Cartier-Tilet 2024-02-14 06:58:17 +01:00
parent 0da40ebf42
commit dd4ebefedc
17 changed files with 442 additions and 126 deletions

View File

@ -10,19 +10,20 @@
"test:unit": "vitest", "test:unit": "vitest",
"build-only": "vite build", "build-only": "vite build",
"type-check": "vue-tsc --build --force", "type-check": "vue-tsc --build --force",
"lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore", "lint": "yarn lint:eslint && yarn lint:oxlint",
"lint:eslint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore",
"lint:oxlint": "oxlint -D perf",
"format": "prettier --write src/" "format": "prettier --write src/"
}, },
"dependencies": { "dependencies": {
"@fontsource/poppins": "^5.0.8", "@fontsource/poppins": "^5.0.8",
"@fontsource/roboto": "^5.0.8", "@fontsource/roboto": "^5.0.8",
"@vueuse/core": "^10.7.2", "@vueuse/core": "^10.7.2",
"@vueuse/rxjs": "^10.7.2",
"less": "^4.2.0", "less": "^4.2.0",
"pinia": "^2.1.7", "pinia": "^2.1.7",
"pocketbase": "^0.21.1", "pocketbase": "^0.21.1",
"rxjs": "^7.8.1", "rxjs": "^7.8.1",
"vue": "^3.4.18", "vue": "^3.4.19",
"vue-router": "^4.2.5" "vue-router": "^4.2.5"
}, },
"devDependencies": { "devDependencies": {
@ -39,6 +40,7 @@
"eslint-plugin-vue": "^9.21.1", "eslint-plugin-vue": "^9.21.1",
"jsdom": "^24.0.0", "jsdom": "^24.0.0",
"npm-run-all2": "^6.1.2", "npm-run-all2": "^6.1.2",
"oxlint": "^0.2.8",
"prettier": "^3.2.5", "prettier": "^3.2.5",
"typescript": "~5.3.3", "typescript": "~5.3.3",
"vite": "^5.1.1", "vite": "^5.1.1",

View File

@ -12,6 +12,10 @@
flex-direction: row; flex-direction: row;
} }
.center {
margin: 0 auto;
}
.flex-center { .flex-center {
align-items: center; align-items: center;
} }
@ -30,6 +34,22 @@
justify-content: space-between; justify-content: space-between;
} }
.flex-even {
justify-content: space-around;
}
.flex-wrap {
.flex;
flex-wrap: wrap;
}
.flex-size-even {
* {
flex: 1;
flex-basis: 100%;
}
}
.themed(@property, @light, @dark) { .themed(@property, @light, @dark) {
@{property}: @light; @{property}: @light;
html.dark & { html.dark & {
@ -67,3 +87,7 @@
.flex-row; .flex-row;
justify-content: end; justify-content: end;
} }
.text-center {
text-align: center;
}

View File

@ -51,15 +51,15 @@ button,
} }
&.h2 { &.h2 {
padding: (@h2-size / 2) (@h2-size * (2 / 3)); padding: (@h2-size / 2) @h2-size;
} }
&.h3 { &.h3 {
padding: (@h3-size / 2) (@h3-size * (2 / 3)); padding: (@h3-size / 2) @h3-size;
} }
&.h4 { &.h4 {
padding: (@h4-size / 2) (@h4-size * (2 / 3)); padding: (@h4-size / 2) @h4-size;
} }
header & { header & {

View File

@ -23,7 +23,7 @@ body {
ul.no-style { ul.no-style {
list-style: none; list-style: none;
list-style-type: none; list-style-type: none;
padding-left: 0; padding: 0;
margin-top: 0; margin-top: 0;
margin-bottom: 0; margin-bottom: 0;
} }

View File

@ -2,9 +2,9 @@
<header class="flex-row-center flex-spread"> <header class="flex-row-center flex-spread">
<RouterLink class="title h4" :to="{ name: 'home' }">{{ appTitle }}</RouterLink> <RouterLink class="title h4" :to="{ name: 'home' }">{{ appTitle }}</RouterLink>
<div class="buttons gap-1rem"> <div class="buttons gap-1rem">
<button @click="toggleDark()" class="secondary">{{ isDark ? 'Dark' : 'Light' }}</button> <button @click="toggleDark()" class="secondary">{{ isDark ? 'Sombre' : 'Clair' }}</button>
<button v-if="!loggedIn" @click="login()" class="secondary">Login</button> <button v-if="!loggedIn" @click="login()" class="secondary">Connexion</button>
<RouterLink v-else :to="{ name: 'account' }" class="button secondary">Account</RouterLink> <RouterLink v-else :to="{ name: 'account' }" class="button secondary">Compte</RouterLink>
</div> </div>
</header> </header>
</template> </template>

View File

@ -1,28 +1,21 @@
<template> <template>
<div class="h3">Bonjour {{ pbStore.auth.username }}&nbsp;!</div> <div class="h2">Bonjour {{ pbStore.auth.username }}&nbsp;!</div>
<div class="campagnes flex-col-center gap-2rem"> <div class="campagnes flex-col-center gap-2rem">
<h1>Campagnes</h1> <div class="h4">Actions</div>
<RouterLink :to="{ name: 'new-campaign' }" class="button">Créer une campagne</RouterLink> <RouterLink :to="{ name: 'campaigns' }" class="button">Mes campagnes</RouterLink>
<ul v-if="campaigns.length > 0">
<li v-for="campaign in campaigns" :key="campaign.id">{{ campaign }}</li>
</ul>
<div v-else>Pas de campagnes pour linstant</div>
</div> </div>
</template> </template>
<script setup="" lang="ts"> <script setup lang="ts">
import { usePocketbaseStore } from '@/stores/pocketbase'; import { usePocketbaseStore } from '@/stores/pocketbase';
import { type RecordModel } from 'pocketbase';
import { onMounted, ref } from 'vue';
import { RouterLink } from 'vue-router'; import { RouterLink } from 'vue-router';
const pbStore = usePocketbaseStore(); const pbStore = usePocketbaseStore();
const campaigns = ref<RecordModel[]>([]);
onMounted(() => {
pbStore.campaign.listCampaigns().subscribe({
next: (result) => (campaigns.value = result),
});
});
</script> </script>
<style scoped lang="less">
.campaigns {
max-width: 80%;
}
</style>

View File

@ -6,12 +6,12 @@
<h2 class="card"> <h2 class="card">
L&apos;application web pour vous accompagner pour votre JDR avec Gégé, le bot discord. L&apos;application web pour vous accompagner pour votre JDR avec Gégé, le bot discord.
</h2> </h2>
<div class="flex-col-center gap-1rem"> <div class="flex-col-center flex-size-even gap-1rem">
<h3>Pourquoi&nbsp;?</h3> <h3>Pourquoi&nbsp;?</h3>
<ul class="flex-row gap-1rem no-style"> <ul class="flex-row gap-1rem no-style">
<li class="card more">Accéder à ses fiche personnage</li> <li class="card more text-center">Créer ses personnages</li>
<li class="card more">Faire évoluer ses personnage</li> <li class="card more text-center">Gérer ses fiche personnage</li>
<li class="card more">Créer ses personnages</li> <li class="card more text-center">Faire évoluer ses personnage</li>
</ul> </ul>
</div> </div>
<button class="h4 raise margin-3rem">Se connecter avec Discord</button> <button class="h4 raise margin-3rem">Se connecter avec Discord</button>

View File

@ -0,0 +1,30 @@
<template>
<div class="card primary flex-col gap-1rem">
<div class="h4" id="name">
{{ props.campaign.name }}
</div>
<div id="dm">
{{ displayName(props.campaign.expand!.game_master!) }}
</div>
<ul id="players" class="no-style">
<li v-for="player in props.campaign.expand!.players" :key="player.id">
{{ displayName(player) }}
</li>
</ul>
</div>
</template>
<script setup lang="ts">
import type { Campaign } from '@/models/Campaign';
import { displayName } from '@/models/User';
const props = defineProps<{
campaign: Campaign;
}>();
</script>
<style scoped lang="less">
.card {
min-width: 20rem;
}
</style>

View File

@ -14,9 +14,8 @@ router.beforeEach((to, from, next) => {
const pbStore = usePocketbaseStore(); const pbStore = usePocketbaseStore();
if (!pbStore.auth.loggedIn && ['home', 'login'].every((path) => path != to.name)) { if (!pbStore.auth.loggedIn && ['home', 'login'].every((path) => path != to.name)) {
next({ name: 'home' }); next({ name: 'home' });
} else {
next();
} }
next();
}); });
app.use(createPinia()); app.use(createPinia());

20
src/models/Campaign.ts Normal file
View File

@ -0,0 +1,20 @@
import { type RecordModel } from 'pocketbase';
import { type User } from './User';
interface CampaignDetails {
game_master?: User;
players?: User[];
}
export interface Campaign extends RecordModel {
expand?: CampaignDetails;
game_master: string;
name: string;
players: string[];
}
export interface NewCampaign {
game_master: string | null;
name: string | null;
players: string[];
}

48
src/models/Character.ts Normal file
View File

@ -0,0 +1,48 @@
import type { RecordModel } from "pocketbase"
interface Effect {
name: string,
effect: string
}
interface BaseSkill {
name: string,
mastery: number,
}
interface FavourableSkill extends BaseSkill {
favourable: boolean
}
export interface PremadeCharacter extends RecordModel {
first_name: string
last_name: string
age: number
heroic_culture: string
particularities: string
description: string
stamina: number
hope: number
defense: number
valour: number
wisdom: number
rewards: Effect[],
virtues: Effect[],
travelling_equipment: Effect[],
image: string
body: number
heart: number
spirit: number
skills: FavourableSkill[]
combat_skills: BaseSkill[]
}
export interface Character extends PremadeCharacter {
campaign: string
current_stamina: number
current_load: number
current_fatigue: number
current_hope: number
status: string
user: string
}

20
src/models/User.ts Normal file
View File

@ -0,0 +1,20 @@
import type { RecordModel } from 'pocketbase';
export interface SimpleUser extends RecordModel {
username: string;
name?: string;
}
export interface User extends SimpleUser {
avatar?: string;
email?: string;
emailVisibility: boolean;
verified: boolean;
}
export function displayName(user: SimpleUser): string {
if (user.name && user.name.trim() !== '') {
return user.name;
}
return user.username;
}

View File

@ -13,6 +13,11 @@ const router = createRouter({
name: 'account', name: 'account',
component: () => import('@/views/AccountView.vue'), component: () => import('@/views/AccountView.vue'),
}, },
{
path: '/campaigns',
name: 'campaigns',
component: () => import('@/views/CampaignsView.vue'),
},
{ {
path: '/new-campaign', path: '/new-campaign',
name: 'new-campaign', name: 'new-campaign',

View File

@ -3,11 +3,8 @@ import { defineStore } from 'pinia';
import { from, map, Observable, tap } from 'rxjs'; import { from, map, Observable, tap } from 'rxjs';
import { computed, ref } from 'vue'; import { computed, ref } from 'vue';
export interface NewCampaign { import type { Campaign, NewCampaign } from '@/models/Campaign';
name: string | null; import type { SimpleUser } from '@/models/User';
game_master: string | null;
players: string[] | null;
}
export const usePocketbaseStore = defineStore('pocketbase', () => { export const usePocketbaseStore = defineStore('pocketbase', () => {
const pb = new PocketBase(import.meta.env.VITE_PB_URL); const pb = new PocketBase(import.meta.env.VITE_PB_URL);
@ -47,22 +44,15 @@ export const usePocketbaseStore = defineStore('pocketbase', () => {
); );
} }
function simpleUserList(): Observable<RecordModel[]> {
return from(
pb.collection('public_users').getFullList({
sort: 'username',
})
);
}
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
// Campaigns // // Campaigns //
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
function listCampaigns(): Observable<RecordModel[]> { function listCampaigns(): Observable<Campaign[]> {
return from( return from(
pb.collection('campaign').getFullList({ pb.collection('campaigns_simple_view').getFullList<Campaign>({
sort: 'name', sort: 'name',
expand: 'players,game_master',
}) })
); );
} }
@ -71,9 +61,20 @@ export const usePocketbaseStore = defineStore('pocketbase', () => {
return from(pb.collection('campaign').create(campaign)); return from(pb.collection('campaign').create(campaign));
} }
/////////////////////////////////////////////////////////////////////////////
// Users //
/////////////////////////////////////////////////////////////////////////////
function allUsersSimple(): Observable<SimpleUser[]> {
return from(
pb.collection('public_users').getFullList<SimpleUser>({
sort: 'username',
})
);
}
return { return {
auth: { auth: {
authData,
authStore, authStore,
loggedIn, loggedIn,
username, username,
@ -88,7 +89,7 @@ export const usePocketbaseStore = defineStore('pocketbase', () => {
createCampaign, createCampaign,
}, },
users: { users: {
simpleUserList, allUsersSimple,
}, },
}; };
}); });

View File

@ -0,0 +1,61 @@
<template>
<h1>Campagnes</h1>
<div class="flex-col gap-2rem">
<div class="flex-col flex-center">
<RouterLink :to="{ name: 'new-campaign' }" class="button">Créer une campagne</RouterLink>
</div>
<h2>Campagnes que je gère</h2>
<div>
<ul
v-if="campaignsGameMaster.length > 0"
class="no-style center flex-wrap flex-size-even flex-even gap-1rem">
<li v-for="campaign in campaignsGameMaster" :key="campaign.id">
<SmallCampaignCard :campaign="campaign" />
</li>
</ul>
<div v-else>Pas de campagne pour linstant</div>
</div>
</div>
<div>
<h2>Campagnes je joue</h2>
<div>
<ul
v-if="campaignsPlayer.length > 0"
class="no-style center flex-wrap flex-size-even flex-even gap-1rem">
<li v-for="campaign in campaignsGameMaster" :key="campaign.id">
<SmallCampaignCard :campaign="campaign" />
</li>
</ul>
<div v-else class="card">Pas de campagne pour linstant</div>
</div>
</div>
</template>
<script setup lang="ts">
import { usePocketbaseStore } from '@/stores/pocketbase';
import SmallCampaignCard from '@/components/SmallCampaignCard.vue';
import { computed, onMounted, ref } from 'vue';
import { RouterLink } from 'vue-router';
import type { Campaign } from '@/models/Campaign';
const pbStore = usePocketbaseStore();
const campaigns = ref<Campaign[]>([]);
const campaignsGameMaster = computed<Campaign[]>(() =>
campaigns.value.filter((campaign) => campaign.game_master === pbStore.auth.userId)
);
const campaignsPlayer = computed<Campaign[]>(() =>
campaigns.value.filter((campaign) =>
campaign.players.some((player) => player === pbStore.auth.userId)
)
);
onMounted(() => {
pbStore.campaign.listCampaigns().subscribe({
next: (result) => (campaigns.value = result),
error: (err) => console.warn(err),
complete: () => console.log('List campaigns completed'),
});
});
</script>

View File

@ -1,9 +1,6 @@
<template> <template>
<h1>Création dune campagne</h1> <h1>Création dune campagne</h1>
<div class="h3 card" v-if="campaign.name"> <form @submit.prevent="createCampaign" class="flex-col gap-2rem card" autocomplete="off">
{{ campaign.name }}
</div>
<form @submit.prevent="createCampaign" class="flex-col gap-2rem card">
<label for="campaign-name" class="flex-col gap-1rem">Nom de la nouvelle campagne</label> <label for="campaign-name" class="flex-col gap-1rem">Nom de la nouvelle campagne</label>
<input <input
name="campaign-name" name="campaign-name"
@ -11,6 +8,13 @@
v-model="campaign.name" v-model="campaign.name"
placeholder="Nom de la nouvelle campagne" /> placeholder="Nom de la nouvelle campagne" />
<label class="flex-col gap-1rem" for="players" autocomplete="off">Joueurs (2 à 10)</label>
<select id="players" name="players" multiple v-model="campaign.players">
<option v-for="user in users" :key="user.id" :value="user.id">
{{ displayName(user) }}
</option>
</select>
<div class="buttons gap-1rem"> <div class="buttons gap-1rem">
<RouterLink :to="{ name: 'home' }" class="button faded">Annuler</RouterLink> <RouterLink :to="{ name: 'home' }" class="button faded">Annuler</RouterLink>
<button type="submit">Envoyer</button> <button type="submit">Envoyer</button>
@ -19,33 +23,33 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import router from '@/router';
import { usePocketbaseStore, type NewCampaign } from '@/stores/pocketbase';
import { type RecordModel } from 'pocketbase';
import { onMounted, ref } from 'vue'; import { onMounted, ref } from 'vue';
import router from '@/router';
import { usePocketbaseStore } from '@/stores/pocketbase';
import { type NewCampaign } from '@/models/Campaign';
import { type SimpleUser, displayName } from '@/models/User';
const pbStore = usePocketbaseStore(); const pbStore = usePocketbaseStore();
const simpleUsers = ref<RecordModel[]>([]); const users = ref<SimpleUser[]>([]);
const campaign = ref<NewCampaign>({ const campaign = ref<NewCampaign>({
name: null, name: null,
game_master: pbStore.auth.userId, game_master: pbStore.auth.userId,
players: null, players: [],
}); });
const createCampaign = () => { const createCampaign = () => {
pbStore.campaign.createCampaign(campaign.value).subscribe({ pbStore.campaign.createCampaign(campaign.value).subscribe({
next: () => { next: () => {
router.push({ name: 'home' }); router.push({ name: 'home' });
router.go(0);
}, },
}); });
}; };
onMounted(() => { onMounted(() => {
pbStore.users.simpleUserList().subscribe({ pbStore.users.allUsersSimple().subscribe({
next: (result) => (simpleUsers.value = result), next: (results) => (users.value = results.filter((user) => user.id !== pbStore.auth.userId)),
error: (err) => console.error('Failed to create campaign:', err), error: (err) => console.warn('Failed to fetch all users', err),
}); });
}); });
</script> </script>

233
yarn.lock
View File

@ -374,6 +374,62 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@oxlint/darwin-arm64@npm:0.2.8":
version: 0.2.8
resolution: "@oxlint/darwin-arm64@npm:0.2.8"
conditions: os=darwin & cpu=arm64
languageName: node
linkType: hard
"@oxlint/darwin-x64@npm:0.2.8":
version: 0.2.8
resolution: "@oxlint/darwin-x64@npm:0.2.8"
conditions: os=darwin & cpu=x64
languageName: node
linkType: hard
"@oxlint/linux-arm64-gnu@npm:0.2.8":
version: 0.2.8
resolution: "@oxlint/linux-arm64-gnu@npm:0.2.8"
conditions: os=linux & cpu=arm64 & libc=glibc
languageName: node
linkType: hard
"@oxlint/linux-arm64-musl@npm:0.2.8":
version: 0.2.8
resolution: "@oxlint/linux-arm64-musl@npm:0.2.8"
conditions: os=linux & cpu=arm64 & libc=musl
languageName: node
linkType: hard
"@oxlint/linux-x64-gnu@npm:0.2.8":
version: 0.2.8
resolution: "@oxlint/linux-x64-gnu@npm:0.2.8"
conditions: os=linux & cpu=x64 & libc=glibc
languageName: node
linkType: hard
"@oxlint/linux-x64-musl@npm:0.2.8":
version: 0.2.8
resolution: "@oxlint/linux-x64-musl@npm:0.2.8"
conditions: os=linux & cpu=x64 & libc=musl
languageName: node
linkType: hard
"@oxlint/win32-arm64@npm:0.2.8":
version: 0.2.8
resolution: "@oxlint/win32-arm64@npm:0.2.8"
conditions: os=win32 & cpu=arm64
languageName: node
linkType: hard
"@oxlint/win32-x64@npm:0.2.8":
version: 0.2.8
resolution: "@oxlint/win32-x64@npm:0.2.8"
conditions: os=win32 & cpu=x64
languageName: node
linkType: hard
"@pkgjs/parseargs@npm:^0.11.0": "@pkgjs/parseargs@npm:^0.11.0":
version: 0.11.0 version: 0.11.0
resolution: "@pkgjs/parseargs@npm:0.11.0" resolution: "@pkgjs/parseargs@npm:0.11.0"
@ -790,7 +846,30 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@vue/compiler-dom@npm:3.4.18, @vue/compiler-dom@npm:^3.3.0": "@vue/compiler-core@npm:3.4.19":
version: 3.4.19
resolution: "@vue/compiler-core@npm:3.4.19"
dependencies:
"@babel/parser": "npm:^7.23.9"
"@vue/shared": "npm:3.4.19"
entities: "npm:^4.5.0"
estree-walker: "npm:^2.0.2"
source-map-js: "npm:^1.0.2"
checksum: 10c0/94b021dc5d29564f94aa0bb7a5b03203e68b332ed165799f88c2de579a58730f4eca9c8c92d041a03843a3b8e378857485f7672be880781fe53133bfafb93d79
languageName: node
linkType: hard
"@vue/compiler-dom@npm:3.4.19":
version: 3.4.19
resolution: "@vue/compiler-dom@npm:3.4.19"
dependencies:
"@vue/compiler-core": "npm:3.4.19"
"@vue/shared": "npm:3.4.19"
checksum: 10c0/348aecff6ade0b023ff6b7bec572ba3fa6e2450530f15acb743a5679c3612fd6d3b15f87aafa00e1d8258f637397657e2e6ae1546c41f838da23a631e9b276f8
languageName: node
linkType: hard
"@vue/compiler-dom@npm:^3.3.0":
version: 3.4.18 version: 3.4.18
resolution: "@vue/compiler-dom@npm:3.4.18" resolution: "@vue/compiler-dom@npm:3.4.18"
dependencies: dependencies:
@ -800,30 +879,30 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@vue/compiler-sfc@npm:3.4.18": "@vue/compiler-sfc@npm:3.4.19":
version: 3.4.18 version: 3.4.19
resolution: "@vue/compiler-sfc@npm:3.4.18" resolution: "@vue/compiler-sfc@npm:3.4.19"
dependencies: dependencies:
"@babel/parser": "npm:^7.23.9" "@babel/parser": "npm:^7.23.9"
"@vue/compiler-core": "npm:3.4.18" "@vue/compiler-core": "npm:3.4.19"
"@vue/compiler-dom": "npm:3.4.18" "@vue/compiler-dom": "npm:3.4.19"
"@vue/compiler-ssr": "npm:3.4.18" "@vue/compiler-ssr": "npm:3.4.19"
"@vue/shared": "npm:3.4.18" "@vue/shared": "npm:3.4.19"
estree-walker: "npm:^2.0.2" estree-walker: "npm:^2.0.2"
magic-string: "npm:^0.30.6" magic-string: "npm:^0.30.6"
postcss: "npm:^8.4.33" postcss: "npm:^8.4.33"
source-map-js: "npm:^1.0.2" source-map-js: "npm:^1.0.2"
checksum: 10c0/8c25ef66d0de168a7f482cc86a2b826d4684c8975cf4cd86974df6f69afbe2b59181d9c5ea8a915099f6ea425d31e988b5100d33a6c71966ee2b75bd3e6a5d0f checksum: 10c0/eb3c6a136c677cf31b624a27f3c23a6511f54b97607a66ef3625ab25ff56370cc589fe2dfa3ef487746a15f4e4033e63e261eb3a76842a5bbe149da1048dfa46
languageName: node languageName: node
linkType: hard linkType: hard
"@vue/compiler-ssr@npm:3.4.18": "@vue/compiler-ssr@npm:3.4.19":
version: 3.4.18 version: 3.4.19
resolution: "@vue/compiler-ssr@npm:3.4.18" resolution: "@vue/compiler-ssr@npm:3.4.19"
dependencies: dependencies:
"@vue/compiler-dom": "npm:3.4.18" "@vue/compiler-dom": "npm:3.4.19"
"@vue/shared": "npm:3.4.18" "@vue/shared": "npm:3.4.19"
checksum: 10c0/34676a7c061ee4ff73692e46524cf27da60e134a4477c8fbafa5c998a718dc9df189a66a4417c5018daa913eeb77a7b0510d35209e7da75c08422fdf7bbcdb79 checksum: 10c0/190dfbe89ad6f662276684ef2931fd67c6e6b7e3d008d6368498481f0632cf4ad06db257f5345336403404050e1791f3ba719dc460029cf9fbbe24abe39adcff
languageName: node languageName: node
linkType: hard linkType: hard
@ -887,45 +966,45 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@vue/reactivity@npm:3.4.18": "@vue/reactivity@npm:3.4.19":
version: 3.4.18 version: 3.4.19
resolution: "@vue/reactivity@npm:3.4.18" resolution: "@vue/reactivity@npm:3.4.19"
dependencies: dependencies:
"@vue/shared": "npm:3.4.18" "@vue/shared": "npm:3.4.19"
checksum: 10c0/f0bc2d126420464603eb56fc93837e1679a462b0f029f38064aea1332ed717a4b717edf473adfd2b487e78deb8da52395fa043191af1ba827f2ddc5bd3efb523 checksum: 10c0/a3febaa2a1a59b428d341db7099238a6182c63d21f1975cf5c3b107a653521163e34ae865d9fca8589b8d3e0d63f3257b8ec57ae276ff47aded5b9797f9583f8
languageName: node languageName: node
linkType: hard linkType: hard
"@vue/runtime-core@npm:3.4.18": "@vue/runtime-core@npm:3.4.19":
version: 3.4.18 version: 3.4.19
resolution: "@vue/runtime-core@npm:3.4.18" resolution: "@vue/runtime-core@npm:3.4.19"
dependencies: dependencies:
"@vue/reactivity": "npm:3.4.18" "@vue/reactivity": "npm:3.4.19"
"@vue/shared": "npm:3.4.18" "@vue/shared": "npm:3.4.19"
checksum: 10c0/73c02094ba6e5f243e5fcdb0ac93a940b2a2ba899dab005d06cff827dcd90289b56fb7248ccc3b40ec36f37c1953647f22585fbec4052765c1e2b4fa6b80d10a checksum: 10c0/03e399a3e5183dd89e471d57a392006bf8145dcd4a2db903e4a07a2951ddd8d258791392da2c9ca8e76def0c9657fd3fbeda8efe0f053099cd73afedd8e9cd61
languageName: node languageName: node
linkType: hard linkType: hard
"@vue/runtime-dom@npm:3.4.18": "@vue/runtime-dom@npm:3.4.19":
version: 3.4.18 version: 3.4.19
resolution: "@vue/runtime-dom@npm:3.4.18" resolution: "@vue/runtime-dom@npm:3.4.19"
dependencies: dependencies:
"@vue/runtime-core": "npm:3.4.18" "@vue/runtime-core": "npm:3.4.19"
"@vue/shared": "npm:3.4.18" "@vue/shared": "npm:3.4.19"
csstype: "npm:^3.1.3" csstype: "npm:^3.1.3"
checksum: 10c0/049588abf076f246e1c2fad58a3b421b680840a9abc3462991f6b221589e4d86d11ca38b23368d92626ef2269ad8663e111e5410c939084d419a63dbc27b5845 checksum: 10c0/b26ef26d06fd89b7549534c9d53eb10047b4adbea305e80730bd50e17b4859ea67ba782af71624cafc7c83f5249da71fc101c566d76e32437a4645303656b51b
languageName: node languageName: node
linkType: hard linkType: hard
"@vue/server-renderer@npm:3.4.18": "@vue/server-renderer@npm:3.4.19":
version: 3.4.18 version: 3.4.19
resolution: "@vue/server-renderer@npm:3.4.18" resolution: "@vue/server-renderer@npm:3.4.19"
dependencies: dependencies:
"@vue/compiler-ssr": "npm:3.4.18" "@vue/compiler-ssr": "npm:3.4.19"
"@vue/shared": "npm:3.4.18" "@vue/shared": "npm:3.4.19"
peerDependencies: peerDependencies:
vue: 3.4.18 vue: 3.4.19
checksum: 10c0/69743873c97fc8db54a4cbd071c6a91aac62a40bcb141b1e47fbfa2d8922b8c3f832eed6a471ed94d3a700d966570c2561f237624848f3fd1f135a3144d1e7af checksum: 10c0/2156362185d62222db060c66d7fa31d2420708f22e491fe1b616008e931be7fcf9cf47e9cca5135359839c269389b475492657948ea3d6756f6a790fcddc34bf
languageName: node languageName: node
linkType: hard linkType: hard
@ -936,6 +1015,13 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@vue/shared@npm:3.4.19":
version: 3.4.19
resolution: "@vue/shared@npm:3.4.19"
checksum: 10c0/bd4a060b0064f0e183e5bb8e346f3be6ff7046793b0765a407e5334860ffd646b28a4ef53652b644e83bd473cea91189377cd83c933bb638d1da143d28f779ff
languageName: node
linkType: hard
"@vue/test-utils@npm:^2.4.4": "@vue/test-utils@npm:^2.4.4":
version: 2.4.4 version: 2.4.4
resolution: "@vue/test-utils@npm:2.4.4" resolution: "@vue/test-utils@npm:2.4.4"
@ -978,18 +1064,6 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@vueuse/rxjs@npm:^10.7.2":
version: 10.7.2
resolution: "@vueuse/rxjs@npm:10.7.2"
dependencies:
"@vueuse/shared": "npm:10.7.2"
vue-demi: "npm:>=0.14.6"
peerDependencies:
rxjs: ">=6.0.0"
checksum: 10c0/83c8ab403ecb396af31d76ecfb476ec003d7a6a54a1682775633dba718204eea92a39983619fd55e30fcefaae0154971b5db985482d62c65468f63be358a76ec
languageName: node
linkType: hard
"@vueuse/shared@npm:10.7.2": "@vueuse/shared@npm:10.7.2":
version: 10.7.2 version: 10.7.2
resolution: "@vueuse/shared@npm:10.7.2" resolution: "@vueuse/shared@npm:10.7.2"
@ -1972,12 +2046,12 @@ __metadata:
"@vue/test-utils": "npm:^2.4.4" "@vue/test-utils": "npm:^2.4.4"
"@vue/tsconfig": "npm:^0.5.1" "@vue/tsconfig": "npm:^0.5.1"
"@vueuse/core": "npm:^10.7.2" "@vueuse/core": "npm:^10.7.2"
"@vueuse/rxjs": "npm:^10.7.2"
eslint: "npm:^8.56.0" eslint: "npm:^8.56.0"
eslint-plugin-vue: "npm:^9.21.1" eslint-plugin-vue: "npm:^9.21.1"
jsdom: "npm:^24.0.0" jsdom: "npm:^24.0.0"
less: "npm:^4.2.0" less: "npm:^4.2.0"
npm-run-all2: "npm:^6.1.2" npm-run-all2: "npm:^6.1.2"
oxlint: "npm:^0.2.8"
pinia: "npm:^2.1.7" pinia: "npm:^2.1.7"
pocketbase: "npm:^0.21.1" pocketbase: "npm:^0.21.1"
prettier: "npm:^3.2.5" prettier: "npm:^3.2.5"
@ -1985,7 +2059,7 @@ __metadata:
typescript: "npm:~5.3.3" typescript: "npm:~5.3.3"
vite: "npm:^5.1.1" vite: "npm:^5.1.1"
vitest: "npm:^1.2.2" vitest: "npm:^1.2.2"
vue: "npm:^3.4.18" vue: "npm:^3.4.19"
vue-router: "npm:^4.2.5" vue-router: "npm:^4.2.5"
vue-tsc: "npm:^1.8.27" vue-tsc: "npm:^1.8.27"
languageName: unknown languageName: unknown
@ -2925,6 +2999,41 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"oxlint@npm:^0.2.8":
version: 0.2.8
resolution: "oxlint@npm:0.2.8"
dependencies:
"@oxlint/darwin-arm64": "npm:0.2.8"
"@oxlint/darwin-x64": "npm:0.2.8"
"@oxlint/linux-arm64-gnu": "npm:0.2.8"
"@oxlint/linux-arm64-musl": "npm:0.2.8"
"@oxlint/linux-x64-gnu": "npm:0.2.8"
"@oxlint/linux-x64-musl": "npm:0.2.8"
"@oxlint/win32-arm64": "npm:0.2.8"
"@oxlint/win32-x64": "npm:0.2.8"
dependenciesMeta:
"@oxlint/darwin-arm64":
optional: true
"@oxlint/darwin-x64":
optional: true
"@oxlint/linux-arm64-gnu":
optional: true
"@oxlint/linux-arm64-musl":
optional: true
"@oxlint/linux-x64-gnu":
optional: true
"@oxlint/linux-x64-musl":
optional: true
"@oxlint/win32-arm64":
optional: true
"@oxlint/win32-x64":
optional: true
bin:
oxlint: bin/oxlint
checksum: 10c0/f795a4eedd60234fab26ecadb41742fd2b4f0d7fd2cd6b4bfe00e979b3d9a466d7fe6eca2d92900aae79aaf515a728e55be67762376d16352f9e6a9e9af0a1d0
languageName: node
linkType: hard
"p-limit@npm:^3.0.2": "p-limit@npm:^3.0.2":
version: 3.1.0 version: 3.1.0
resolution: "p-limit@npm:3.1.0" resolution: "p-limit@npm:3.1.0"
@ -3996,21 +4105,21 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"vue@npm:^3.4.18": "vue@npm:^3.4.19":
version: 3.4.18 version: 3.4.19
resolution: "vue@npm:3.4.18" resolution: "vue@npm:3.4.19"
dependencies: dependencies:
"@vue/compiler-dom": "npm:3.4.18" "@vue/compiler-dom": "npm:3.4.19"
"@vue/compiler-sfc": "npm:3.4.18" "@vue/compiler-sfc": "npm:3.4.19"
"@vue/runtime-dom": "npm:3.4.18" "@vue/runtime-dom": "npm:3.4.19"
"@vue/server-renderer": "npm:3.4.18" "@vue/server-renderer": "npm:3.4.19"
"@vue/shared": "npm:3.4.18" "@vue/shared": "npm:3.4.19"
peerDependencies: peerDependencies:
typescript: "*" typescript: "*"
peerDependenciesMeta: peerDependenciesMeta:
typescript: typescript:
optional: true optional: true
checksum: 10c0/ed62926d19ca9b92662d65221be94f24383202e3bc565e000f75511250c7808f031272e1fdd83da28da12e9ca3444af31d57392f11b5b890467aca9827ad53a9 checksum: 10c0/90d45a30b096d3a2445314cf5a94db6f56b854bd483a706bc7ec358b555e2c6dba8ce7b6a976d52af2a8ba92fb3caab4b77b50886f732857320073753152528d
languageName: node languageName: node
linkType: hard linkType: hard