Skip to content

Submission

Submission

Documentation technique

Type de ressource : Schéma Sanity (Document)
Fichier source : apps/studio/schemaTypes/submission.ts
Statut : Actif
Slice : 4 (Formulaire contact)
Version : 1.0

1. Vue d’ensemble (DOC)

1.1. Description

Schéma pour les soumissions de formulaire de contact. Contient les informations du soumetteur (nom, email, message), le statut de traitement, et les horodatages de soumission et de traitement. Créé automatiquement par le worker submission-processor.

1.2. Objectif

  • Modéliser les soumissions du formulaire de contact
  • Permettre le suivi du statut de traitement
  • Faciliter la gestion des soumissions dans le Sanity Studio
  • Supporter l’historique des soumissions avec horodatage

1.3. Cas d’usage

  • Stockage des soumissions du formulaire de contact
  • Suivi du statut de traitement (pending, processed, rejected)
  • Historique des soumissions avec horodatage
  • Interface pour la gestion des soumissions dans le Sanity Studio

1.4. Relations avec d’autres schémas

Relation Schéma Type Description
Dépend de Aucun - Schéma indépendant
Utilisé par Aucun - Créé automatiquement par workers, non référencé

2. Structure des données (DOC)

2.1. Champs principaux

Nom du champ Type Obligatoire Description Validation
name string ✅ Nom du soumetteur Rule.required().min(2).max(100)
email string ✅ Email du soumetteur Rule.required().email()
message text ✅ Message du formulaire de contact Rule.required().min(10).max(2000)
status string ✅ Statut de traitement Options: pending, processed, rejected
submittedAt datetime ✅ Date et heure de soumission initialValue: new Date().toISOString()
processedAt datetime ❌ Date et heure de traitement Aucune

2.2. Champs SEO

Aucun champ SEO spécifique n’est implémenté dans ce schéma.

2.3. Champs de contenu riche

Aucun champ de contenu riche n’est implémenté dans ce schéma.

3. Contrats d’Entrée/Sortie (SPEC)

3.1. Inputs (création/modification)

Champ Type Validation Description
name string Rule.required().min(2).max(100) Nom du soumetteur
email string Rule.required().email() Email du soumetteur
message text Rule.required().min(10).max(2000) Message du formulaire
status string Options: pending, processed, rejected Statut de traitement
submittedAt datetime initialValue: new Date().toISOString() Date de soumission
processedAt datetime Aucune Date de traitement (optionnel)

3.2. Outputs (structure du document)1/2

Champ Type Description
_id string ID unique du document
_type string Type du document (submission)
_createdAt string Date de création (généré par Sanity)
_updatedAt string Date de dernière modification (généré par Sanity)
name string Nom du soumetteur

3.2. Outputs (structure du document)2/2

Champ Type Description
email string Email du soumetteur
message string Message du formulaire
status string Statut de traitement
submittedAt string Date et heure de soumission
processedAt string Date et heure de traitement (optionnel)

3.3. États du document

État Description Transition
pending Soumission en attente de traitement → processed ou rejected
processed Soumission traitée avec succès → pending (retraitement)
rejected Soumission rejetée → pending (réexamen)

4. Implémentation (CODE)

4.1. Code du schéma1/2

4.1. Code du schéma2/2

apps/studio/schemaTypes/submission.ts
import { defineType, defineField } from 'sanity'
export default defineType({
name: 'submission',
title: 'Form Submission',
type: 'document',
fields: [
defineField({
name: 'name',
title: 'Name',
type: 'string',
description: 'Nom du soumetteur',
validation: (Rule) => Rule.required().min(2).max(100),
}),
defineField({
name: 'email',
title: 'Email',
type: 'string',
description: 'Email du soumetteur',
validation: (Rule) => Rule.required().email(),
}),
defineField({
name: 'message',
title: 'Message',
type: 'text',
description: 'Message du formulaire de contact',
validation: (Rule) => Rule.required().min(10).max(2000),
}),
defineField({
name: 'status',
title: 'Status',
type: 'string',
options: {
list: [
{ title: 'Pending', value: 'pending' },
{ title: 'Processed', value: 'processed' },
{ title: 'Rejected', value: 'rejected' },
],
layout: 'radio',
},
initialValue: 'pending',
}),
defineField({
name: 'submittedAt',
title: 'Submitted At',
type: 'datetime',
description: 'Date et heure de soumission',
initialValue: () => new Date().toISOString(),
}),
defineField({
name: 'processedAt',
title: 'Processed At',
type: 'datetime',
description: 'Date et heure de traitement',
}),
],
preview: {
select: {
title: 'name',
subtitle: 'email',
description: 'message',
},
prepare({ title, subtitle, description }) {
return {
title,
subtitle: `${subtitle} - ${description?.substring(0, 50)}...`,
}
},
},
orderings: [
{
title: 'Submitted At (Newest)',
name: 'submittedAtDesc',
by: [{field: 'submittedAt', direction: 'desc'}],
},
{
title: 'Submitted At (Oldest)',
name: 'submittedAtAsc',
by: [{field: 'submittedAt', direction: 'asc'}],
},
],
})

4.2. Requêtes GROQ associées

Requête principale (soumissions pending)

*[_type == "submission" && status == "pending"] {
_id,
name,
email,
message,
submittedAt
} | order(submittedAt desc)

Requête détaillée (page unitaire)

*[_type == "submission" && _id == $id][0] {
_id,
name,
email,
message,
status,
submittedAt,
processedAt
}

4.3. Types TypeScript (génération automatique)

Non implémenté - sanity-typegen n’est pas configuré dans le projet actuel.

// Types à implémenter manuellement si nécessaire
export type Submission = {
_id: string;
_type: 'submission';
name: string;
email: string;
message: string;
status: 'pending' | 'processed' | 'rejected';
submittedAt: string;
processedAt?: string;
};

5. Tests attendus (TEST)

5.1. Tests unitaires

Scénario Description Résultat attendu
Validation du nom Créer une soumission sans nom Erreur de validation
Validation de l’email Créer une soumission avec email invalide Erreur de validation
Validation du message Créer une soumission avec message < 10 caractères Erreur de validation
Limite du message Créer une soumission avec message > 2000 caractères Erreur de validation
Status par défaut Créer une soumission sans status Valeur par défaut pending appliquée

5.2. Tests d’intégration

Scénario Dépendances Description Résultat attendu
Création par worker Form-handler → Queue → Submission-processor Soumettre un formulaire via l’API Document créé dans Sanity
Validation Zod Frontend + Worker Validation des entrées côté frontend Erreur retournée si validation échoue
Stockage dans Sanity Submission-processor + Sanity API Création du document dans Sanity Document créé avec tous les champs

5.3. Tests E2E

Scénario Parcours utilisateur Description Résultat attendu
Soumission → Traitement Formulaire → API → Sanity → Studio Soumettre un formulaire complet Document visible dans Sanity Studio
Traitement manuel Studio → Changement status Passer le status de pending à processed Status changé avec succès
Tri par date Studio → Ordering Trier les soumissions par date Soumissions triées correctement

6. Intégration (INTÉG)

6.1. Intégration avec les composants

Composant Type Rôle Méthode d’intégration
Form-handler Worker L3 Validation et mise en queue Reçoit la soumission et l’envoie dans la Queue
Submission-processor Worker L3 Création du document Sanity Consomme la Queue et crée le document
Sanity Studio L1 Gestion des soumissions Interface pour visualiser et traiter les soumissions
Formulaire contact L2 Soumission du formulaire Envoie les données vers l’API submit

6.2. Points d’attention

  • Ce schéma est créé automatiquement par le worker submission-processor
  • Le champ submittedAt est initialisé par le frontend, processedAt par le worker
  • Les orderings personnalisés permettent un tri par date de soumission
  • Le preview affiche un résumé du message (50 premiers caractères)
  • Validation stricte des entrées côté frontend (Zod) et backend (Sanity)
  • Le flux complet : Formulaire → API → form-handler → Queue → submission-processor → Sanity

6.3. Vérification de cohérence

  • Le schéma ne casse aucun schéma existant
  • Les requêtes GROQ retournent les données attendues
  • Les types TypeScript sont générés correctement (à implémenter)
  • Le flux de soumission fonctionne de bout en bout

7. Sécurité

7.1. Mécanismes de sécurité

  • ✅ Validation stricte des entrées côté frontend (Zod)
  • ✅ Validation des entrées côté backend (Sanity)
  • ✅ Les permissions Sanity sont configurées par rôle
  • ✅ Les emails sont validés automatiquement

7.2. Validation des entrées

  • ✅ Le champ name est validé (min 2, max 100 caractères)
  • ✅ Le champ email est validé (format email)
  • ✅ Le champ message est validé (min 10, max 2000 caractères)
  • ✅ Le champ status est limité aux options valides

8. Performance et limites

8.1. Limites Sanity

Limite Valeur Stratégie d’optimisation
Taille du document 16 MB Éviter les messages trop volumineux
Profondeur des références 10 niveaux Pas applicable (pas de références)

8.2. Optimisations appliquées

  • ✅ Utilisation de Queue Cloudflare pour le traitement asynchrone
  • ✅ Limitation de la taille du message (max 2000 caractères)
  • ✅ Orderings personnalisés pour un tri efficace

9. Débogage et troubleshooting

9.1. Problèmes courants

Symptôme Cause probable Solution
Soumission non créée Queue non configurée Vérifier la configuration Queue dans wrangler.toml
Document sans processedAt Worker échoué Vérifier les logs du worker submission-processor
Validation échoue Données invalides Vérifier les règles de validation Zod et Sanity
Status ne change pas Permissions insuffisantes Vérifier les permissions Sanity Studio

9.2. Commandes de debug

Terminal window
# Extraire le schéma depuis Sanity
npx sanity schema extract
# Générer les types TypeScript (à implémenter)
npx sanity typegen generate
# Logs du worker submission-processor
wrangler tail submission-processor

10. Bonnes pratiques

10.1. Architecture

  • ✅ Toujours utiliser des types générés par sanity-typegen (à implémenter)
  • ✅ Centraliser les requêtes GROQ dans src/lib/queries.ts (à implémenter)
  • ✅ Documenter les champs et leurs validations

10.2. Code

  • ✅ Utiliser defineField pour chaque champ
  • ✅ Configurer le preview pour une meilleure UX dans Studio
  • ✅ Utiliser des validations appropriées
  • ✅ Configurer les orderings pour un tri efficace

10.3. Maintenance

  • ✅ Mettre à jour ce fichier lors de toute modification du schéma
  • ✅ Régénérer les types après modification (à implémenter)
  • ✅ Tester le flux de soumission après modification

11. Évolutions et roadmap

11.1. Améliorations planifiées

  • Implémentation de sanity-typegen pour la génération de types
  • Ajout de champs pour les pièces jointes
  • Notification automatique lors de nouvelles soumissions
  • Centralisation des requêtes GROQ dans un fichier dédié

11.2. Limitations connues

  • ❌ Pas de champs SEO spécifiques
  • ❌ Types TypeScript non générés automatiquement
  • ❌ Pas de support pour les pièces jointes
  • ❌ Pas de notification automatique

12. Ressources liées1/2

  • Documentation Sanity : Schema Types
  • DAT L1 : §4 - Modélisation et Schémas des Données
  • Schémas dépendants : Aucun (schéma indépendant)
  • Workers associés : services/form-handler, services/submission-processor

12. Ressources liées2/2

  • Pages Astro : apps/web/src/pages/contact.astro, apps/web/src/pages/api/submit.ts
  • Queue Cloudflare : submissions-queue-dev / submissions-queue-prod
  • Configuration : services/form-handler/wrangler.toml, services/submission-processor/wrangler.toml

13. Historique des modifications

Date Version Description Auteur
2026-09-15 1.0 Création initiale Devin
Switch to normal mode

Contents