classe et espece
This commit is contained in:
@@ -41,4 +41,23 @@ const especes = defineCollection({
|
|||||||
.passthrough(),
|
.passthrough(),
|
||||||
});
|
});
|
||||||
|
|
||||||
export const collections = { journal, classes, especes };
|
const personnages = defineCollection({
|
||||||
|
loader: obsidianLoader("personnages"),
|
||||||
|
schema: z
|
||||||
|
.object({
|
||||||
|
nom: z.string(),
|
||||||
|
espece: z.string(),
|
||||||
|
niveau_global: z.number().default(1),
|
||||||
|
classes_detail: z
|
||||||
|
.array(
|
||||||
|
z.object({
|
||||||
|
nom: z.string(),
|
||||||
|
niveau: z.number(),
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.default([]),
|
||||||
|
})
|
||||||
|
.passthrough(),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const collections = { journal, classes, especes, personnages };
|
||||||
|
|||||||
10
src/content/personnages/bulle.md
Normal file
10
src/content/personnages/bulle.md
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
---
|
||||||
|
nom: "Bulle"
|
||||||
|
espece: "fee"
|
||||||
|
niveau_global: 2
|
||||||
|
classes_detail:
|
||||||
|
- nom: "clerc"
|
||||||
|
niveau: 1
|
||||||
|
---
|
||||||
|
|
||||||
|
Fille de la lune et du savoir ancestral.
|
||||||
10
src/content/personnages/gmas.md
Normal file
10
src/content/personnages/gmas.md
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
---
|
||||||
|
nom: "G'Mas"
|
||||||
|
espece: "grung"
|
||||||
|
niveau_global: 2
|
||||||
|
classes_detail:
|
||||||
|
- nom: "moine"
|
||||||
|
niveau: 1
|
||||||
|
---
|
||||||
|
|
||||||
|
Fille de la lune et du savoir ancestral.
|
||||||
10
src/content/personnages/gurdill.md
Normal file
10
src/content/personnages/gurdill.md
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
---
|
||||||
|
nom: "Gurdill"
|
||||||
|
espece: "nain"
|
||||||
|
niveau_global: 2
|
||||||
|
classes_detail:
|
||||||
|
- nom: "barbare"
|
||||||
|
niveau: 1
|
||||||
|
---
|
||||||
|
|
||||||
|
Brute au grand coeur, forgé dans les montagnes.
|
||||||
10
src/content/personnages/jinn.md
Normal file
10
src/content/personnages/jinn.md
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
---
|
||||||
|
nom: "Jinn"
|
||||||
|
espece: "genasi"
|
||||||
|
niveau_global: 2
|
||||||
|
classes_detail:
|
||||||
|
- nom: "barde"
|
||||||
|
niveau: 1
|
||||||
|
---
|
||||||
|
|
||||||
|
Brute au grand coeur, forgé dans les montagnes.
|
||||||
10
src/content/personnages/nyrae.md
Normal file
10
src/content/personnages/nyrae.md
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
---
|
||||||
|
nom: "Nyrae"
|
||||||
|
espece: "tabaxi"
|
||||||
|
niveau_global: 2
|
||||||
|
classes_detail:
|
||||||
|
- nom: "druide"
|
||||||
|
niveau: 1
|
||||||
|
---
|
||||||
|
|
||||||
|
Brute au grand coeur, forgé dans les montagnes.
|
||||||
@@ -4,57 +4,131 @@ import GameLayout from "../layouts/GameLayout.astro";
|
|||||||
|
|
||||||
const classes = await getCollection("classes");
|
const classes = await getCollection("classes");
|
||||||
const especes = await getCollection("especes");
|
const especes = await getCollection("especes");
|
||||||
|
const personnages = await getCollection("personnages");
|
||||||
|
|
||||||
|
// Groupement pour les classes (Gestion multiclassage)
|
||||||
|
const classData = personnages.reduce((acc, p) => {
|
||||||
|
// On vérifie si classes_detail existe, sinon on simule un tableau avec la classe de base
|
||||||
|
const details = p.data.classes_detail || [
|
||||||
|
{ nom: p.data.classe, niveau: p.data.niveau_global || 1 },
|
||||||
|
];
|
||||||
|
|
||||||
|
details.forEach((c) => {
|
||||||
|
if (!c.nom) return;
|
||||||
|
const key = c.nom.toLowerCase();
|
||||||
|
if (!acc[key]) acc[key] = [];
|
||||||
|
|
||||||
|
acc[key].push({
|
||||||
|
nom: p.data.nom,
|
||||||
|
niveau_classe: c.niveau,
|
||||||
|
niveau_total: p.data.niveau_global || c.niveau,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return acc;
|
||||||
|
}, {});
|
||||||
|
|
||||||
|
// Groupement pour l'espèce
|
||||||
|
const especeData = personnages.reduce((acc, p) => {
|
||||||
|
if (!p.data.espece) return acc;
|
||||||
|
const key = p.data.espece.toLowerCase();
|
||||||
|
if (!acc[key]) acc[key] = [];
|
||||||
|
acc[key].push({
|
||||||
|
nom: p.data.nom,
|
||||||
|
niveau: p.data.niveau_global || 1,
|
||||||
|
});
|
||||||
|
return acc;
|
||||||
|
}, {});
|
||||||
---
|
---
|
||||||
|
|
||||||
<GameLayout title="Création de Personnage">
|
<GameLayout title="Création de Personnage">
|
||||||
<div class="creation-container">
|
<div class="creation-container">
|
||||||
<!-- Section for Classes -->
|
|
||||||
<section class="character-select">
|
<section class="character-select">
|
||||||
<h2 class="dnd-title">Choisissez votre Classe</h2>
|
<h2 class="dnd-title">Choisissez votre Classe</h2>
|
||||||
<div class="dnd-bar"></div>
|
<div class="dnd-bar"></div>
|
||||||
<p class="dnd-intro">
|
<p class="dnd-intro">
|
||||||
La classe définit vos compétences et votre rôle dans l'aventure.
|
La classe définit vos compétences et votre rôle dans l'aventure.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<div class="class-grid">
|
<div class="class-grid">
|
||||||
{
|
{
|
||||||
classes.map((charClass) => (
|
classes.map((charClass) => {
|
||||||
<div class="class-card">
|
const charactersInClass =
|
||||||
<h3>{charClass.data.title}</h3>
|
classData[charClass.id.toLowerCase()] || [];
|
||||||
<p>{charClass.data.description}</p>
|
return (
|
||||||
<a
|
<div class="class-card">
|
||||||
href={`/classes/${charClass.id}`}
|
<h3>{charClass.data.title}</h3>
|
||||||
class="select-button"
|
|
||||||
>
|
<div class="bubble-container">
|
||||||
Détails
|
{charactersInClass.map((p) => (
|
||||||
</a>
|
<div class="notification-bubble">
|
||||||
</div>
|
<span class="p-name">{p.nom}</span>
|
||||||
))
|
<span class="p-lvl">
|
||||||
|
Niv.{p.niveau_classe}
|
||||||
|
</span>
|
||||||
|
{p.niveau_total >
|
||||||
|
p.niveau_classe && (
|
||||||
|
<span
|
||||||
|
class="multiclass-dot"
|
||||||
|
title="Multiclassé"
|
||||||
|
>
|
||||||
|
+
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p>{charClass.data.description}</p>
|
||||||
|
<a
|
||||||
|
href={`/classes/${charClass.id}`}
|
||||||
|
class="select-button"
|
||||||
|
>
|
||||||
|
Détails
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<!-- Section for Species -->
|
|
||||||
<section class="character-select">
|
<section class="character-select">
|
||||||
<h2 class="dnd-title">Choisissez votre Espèce</h2>
|
<h2 class="dnd-title">Choisissez votre Espèce</h2>
|
||||||
<div class="dnd-bar"></div>
|
<div class="dnd-bar"></div>
|
||||||
<p class="dnd-intro">
|
<p class="dnd-intro">
|
||||||
L'espèce influence votre apparence, votre histoire et certaines
|
L'espèce influence votre apparence et votre histoire.
|
||||||
de vos aptitudes.
|
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<div class="class-grid">
|
<div class="class-grid">
|
||||||
{
|
{
|
||||||
especes.map((espece) => (
|
especes.map((espece) => {
|
||||||
<div class="class-card">
|
const charactersInEspece =
|
||||||
<h3>{espece.data.title}</h3>
|
especeData[espece.id.toLowerCase()] || [];
|
||||||
<p>{espece.data.description}</p>
|
return (
|
||||||
<a
|
<div class="class-card">
|
||||||
href={`/especes/${espece.id}`}
|
<h3>{espece.data.title}</h3>
|
||||||
class="select-button"
|
|
||||||
>
|
<div class="bubble-container">
|
||||||
Détails
|
{charactersInEspece.map((p) => (
|
||||||
</a>
|
<div class="notification-bubble species">
|
||||||
</div>
|
<span class="p-name">{p.nom}</span>
|
||||||
))
|
<span class="p-lvl">
|
||||||
|
Niv.{p.niveau}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p>{espece.data.description}</p>
|
||||||
|
<a
|
||||||
|
href={`/especes/${espece.id}`}
|
||||||
|
class="select-button"
|
||||||
|
>
|
||||||
|
Détails
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
@@ -95,12 +169,10 @@ const especes = await getCollection("especes");
|
|||||||
.dnd-intro {
|
.dnd-intro {
|
||||||
font-family: "Cinzel", serif;
|
font-family: "Cinzel", serif;
|
||||||
font-size: 0.9rem;
|
font-size: 0.9rem;
|
||||||
margin-top: 1rem;
|
margin: 1rem auto;
|
||||||
opacity: 0.8;
|
opacity: 0.8;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
max-width: 600px;
|
max-width: 600px;
|
||||||
margin-left: auto;
|
|
||||||
margin-right: auto;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.class-grid {
|
.class-grid {
|
||||||
@@ -133,7 +205,47 @@ const especes = await getCollection("especes");
|
|||||||
font-family: "Playfair Display", serif;
|
font-family: "Playfair Display", serif;
|
||||||
font-size: 1.8rem;
|
font-size: 1.8rem;
|
||||||
color: #c89b3c;
|
color: #c89b3c;
|
||||||
margin: 0 0 1rem 0;
|
margin: 0 0 0.5rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bubble-container {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 6px;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
min-height: 28px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.notification-bubble {
|
||||||
|
background: #3a352a;
|
||||||
|
color: white;
|
||||||
|
font-family: "Cinzel", serif;
|
||||||
|
font-size: 0.7rem;
|
||||||
|
padding: 2px 10px;
|
||||||
|
border-radius: 20px;
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 5px;
|
||||||
|
transition: transform 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.notification-bubble:hover {
|
||||||
|
transform: scale(1.05);
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.p-lvl {
|
||||||
|
font-size: 0.6rem;
|
||||||
|
opacity: 0.8;
|
||||||
|
padding-left: 5px;
|
||||||
|
border-left: 1px solid rgba(255, 255, 255, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.multiclass-dot {
|
||||||
|
color: #c89b3c;
|
||||||
|
font-weight: bold;
|
||||||
|
margin-left: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.class-card p {
|
.class-card p {
|
||||||
@@ -152,12 +264,8 @@ const especes = await getCollection("especes");
|
|||||||
border: 1px solid #c89b3c;
|
border: 1px solid #c89b3c;
|
||||||
padding: 0.5rem 1rem;
|
padding: 0.5rem 1rem;
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
cursor: pointer;
|
|
||||||
transition:
|
|
||||||
background-color 0.3s,
|
|
||||||
color 0.3s;
|
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
display: inline-block;
|
transition: all 0.3s;
|
||||||
}
|
}
|
||||||
|
|
||||||
.select-button:hover {
|
.select-button:hover {
|
||||||
|
|||||||
Reference in New Issue
Block a user