Suggest on creation + distance in kms
This commit is contained in:
+58
-2
@@ -179,6 +179,48 @@ export const parsedFeatures: ParsedFeature[] = [
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Détecter un événement similaire déjà relayé",
|
||||
"tags": [],
|
||||
"steps": [
|
||||
{
|
||||
"keyword": "Étant donné que ",
|
||||
"text": "l'écran \"create-event\" est affiché"
|
||||
},
|
||||
{
|
||||
"keyword": "Alors",
|
||||
"text": "le formulaire permet de détecter les doublons"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Importer un événement depuis une source externe",
|
||||
"tags": [],
|
||||
"steps": [
|
||||
{
|
||||
"keyword": "Étant donné que ",
|
||||
"text": "l'écran \"create-event\" est affiché"
|
||||
},
|
||||
{
|
||||
"keyword": "Alors",
|
||||
"text": "le formulaire permet d'importer depuis Mobilizon ou Transiscope"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Pas d'alerte doublon lors d'un import externe",
|
||||
"tags": [],
|
||||
"steps": [
|
||||
{
|
||||
"keyword": "Étant donné que ",
|
||||
"text": "l'écran \"create-event\" est affiché"
|
||||
},
|
||||
{
|
||||
"keyword": "Alors",
|
||||
"text": "l'import externe ne déclenche pas d'alerte doublon"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Modifier un événement",
|
||||
"tags": [],
|
||||
@@ -196,7 +238,7 @@ export const parsedFeatures: ParsedFeature[] = [
|
||||
}
|
||||
],
|
||||
"filePath": "features/event/us-13-creer-evenement.feature",
|
||||
"rawContent": "# language: fr\n@EVENT @priority-1\nFonctionnalité: US-13 Relayer/Modifier/Supprimer un événement\n En tant qu'utilisateur\n Je peux relayer/modifier/supprimer un événement\n En choisissant les dates, horaires, lieu et thématique\n Afin de relayer/présenter le contenu de cet événement et le catégoriser\n\n Contexte:\n Étant donné que je suis connecté en tant qu'utilisateur\n\n Scénario: Accéder au formulaire de relai d'événement\n Étant donné que je suis sur la page \"accueil\"\n Quand je navigue vers \"relayer un événement\"\n Alors je vois l'écran \"create-event\"\n\n Scénario: Vérifier les champs obligatoires du formulaire\n Étant donné que l'écran \"create-event\" est affiché\n Alors le formulaire contient les champs obligatoires suivants:\n | Nom de l'événement |\n | Date de début |\n | Heure de début |\n | Lieu |\n | Thématique |\n\n Scénario: Vérifier la présence du bouton de relai\n Étant donné que je suis sur la page \"relayer un événement\"\n Alors l'écran contient une section \"Relayer l'événement\"\n\n Scénario: Pouvoir annuler le relai d'événement\n Étant donné que je suis sur la page \"relayer un événement\"\n Alors je peux annuler et revenir à l'écran précédent\n\n Scénario: Modifier un événement\n * Scénario non implémenté\n\n Scénario: Supprimer un événement\n * Scénario non implémenté\n\n Scénario: Retirer une organisation (personne ou structure)\n * Scénario non implémenté\n",
|
||||
"rawContent": "# language: fr\n@EVENT @priority-1\nFonctionnalité: US-13 Relayer/Modifier/Supprimer un événement\n En tant qu'utilisateur\n Je peux relayer/modifier/supprimer un événement\n En choisissant les dates, horaires, lieu et thématique\n Afin de relayer/présenter le contenu de cet événement et le catégoriser\n\n Contexte:\n Étant donné que je suis connecté en tant qu'utilisateur\n\n Scénario: Accéder au formulaire de relai d'événement\n Étant donné que je suis sur la page \"accueil\"\n Quand je navigue vers \"relayer un événement\"\n Alors je vois l'écran \"create-event\"\n\n Scénario: Vérifier les champs obligatoires du formulaire\n Étant donné que l'écran \"create-event\" est affiché\n Alors le formulaire contient les champs obligatoires suivants:\n | Nom de l'événement |\n | Date de début |\n | Heure de début |\n | Lieu |\n | Thématique |\n\n Scénario: Vérifier la présence du bouton de relai\n Étant donné que je suis sur la page \"relayer un événement\"\n Alors l'écran contient une section \"Relayer l'événement\"\n\n Scénario: Pouvoir annuler le relai d'événement\n Étant donné que je suis sur la page \"relayer un événement\"\n Alors je peux annuler et revenir à l'écran précédent\n\n Scénario: Détecter un événement similaire déjà relayé\n Étant donné que l'écran \"create-event\" est affiché\n Alors le formulaire permet de détecter les doublons\n\n Scénario: Importer un événement depuis une source externe\n Étant donné que l'écran \"create-event\" est affiché\n Alors le formulaire permet d'importer depuis Mobilizon ou Transiscope\n\n Scénario: Pas d'alerte doublon lors d'un import externe\n Étant donné que l'écran \"create-event\" est affiché\n Alors l'import externe ne déclenche pas d'alerte doublon\n\n Scénario: Modifier un événement\n * Scénario non implémenté\n\n Scénario: Supprimer un événement\n * Scénario non implémenté\n\n Scénario: Retirer une organisation (personne ou structure)\n * Scénario non implémenté\n",
|
||||
"screenIds": [
|
||||
"create-event",
|
||||
"home"
|
||||
@@ -500,6 +542,20 @@ export const parsedFeatures: ParsedFeature[] = [
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Voir la localisation des événements",
|
||||
"tags": [],
|
||||
"steps": [
|
||||
{
|
||||
"keyword": "Étant donné que ",
|
||||
"text": "je suis sur la page \"profil utilisateur\""
|
||||
},
|
||||
{
|
||||
"keyword": "Alors",
|
||||
"text": "les événements affichent leur localisation et distance"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Voir le formulaire de contact",
|
||||
"tags": [],
|
||||
@@ -535,7 +591,7 @@ export const parsedFeatures: ParsedFeature[] = [
|
||||
}
|
||||
],
|
||||
"filePath": "features/user/us-10-profil-participant.feature",
|
||||
"rawContent": "# language: fr\n@USER @priority-1\nFonctionnalité: US-10 Visualiser la fiche/le profil d'un participant\n En tant qu'utilisateur\n Je peux sélectionner un individu dans la liste des inscrits à un événement/atelier\n Afin de voir les événements auxquels la personne a participé et voir un formulaire de contact\n\n Contexte:\n Étant donné que je suis connecté en tant qu'utilisateur\n\n Scénario: Accéder au profil d'un participant\n Étant donné que je suis sur la page \"détail événement\"\n Quand je clique sur un participant\n Alors je vois l'écran \"user-profile\"\n\n Scénario: Voir les événements du participant\n Étant donné que je suis sur la page \"profil utilisateur\"\n Alors je peux voir les événements auxquels l'utilisateur a participé\n\n Scénario: Voir le formulaire de contact\n Étant donné que je suis sur la page \"profil utilisateur\"\n Alors je peux contacter l'utilisateur\n\n Scénario: Vérifier les informations du profil\n * Scénario non implémenté\n\n Scénario: Voir les détails du profil utilisateur\n Étant donné que je suis sur la page \"profil utilisateur\"\n Alors l'écran affiche les informations du profil\n",
|
||||
"rawContent": "# language: fr\n@USER @priority-1\nFonctionnalité: US-10 Visualiser la fiche/le profil d'un participant\n En tant qu'utilisateur\n Je peux sélectionner un individu dans la liste des inscrits à un événement/atelier\n Afin de voir les événements auxquels la personne a participé et voir un formulaire de contact\n\n Contexte:\n Étant donné que je suis connecté en tant qu'utilisateur\n\n Scénario: Accéder au profil d'un participant\n Étant donné que je suis sur la page \"détail événement\"\n Quand je clique sur un participant\n Alors je vois l'écran \"user-profile\"\n\n Scénario: Voir les événements du participant\n Étant donné que je suis sur la page \"profil utilisateur\"\n Alors je peux voir les événements auxquels l'utilisateur a participé\n\n Scénario: Voir la localisation des événements\n Étant donné que je suis sur la page \"profil utilisateur\"\n Alors les événements affichent leur localisation et distance\n\n Scénario: Voir le formulaire de contact\n Étant donné que je suis sur la page \"profil utilisateur\"\n Alors je peux contacter l'utilisateur\n\n Scénario: Vérifier les informations du profil\n * Scénario non implémenté\n\n Scénario: Voir les détails du profil utilisateur\n Étant donné que je suis sur la page \"profil utilisateur\"\n Alors l'écran affiche les informations du profil\n",
|
||||
"screenIds": [
|
||||
"event-detail",
|
||||
"user-profile"
|
||||
|
||||
@@ -206,6 +206,27 @@ export const stepDefinitions: StepDefinitionInfo[] = [
|
||||
"sourceCode": "Then('le champ {string} est présent', async function (this: FestipodWorld, fieldName: string) {\n const source = this.getRenderedText();\n // Check that field label exists in screen source\n const escapedName = fieldName.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n const pattern = new RegExp(`>${escapedName}[^<]*<`);\n expect(pattern.test(source), `Field \"${fieldName}\" should be present in screen`).to.be.true;\n});",
|
||||
"lineNumber": 53
|
||||
},
|
||||
{
|
||||
"pattern": "le formulaire permet de détecter les doublons",
|
||||
"keyword": "Then",
|
||||
"file": "form.steps.ts",
|
||||
"sourceCode": "Then('le formulaire permet de détecter les doublons', async function (this: FestipodWorld) {\n expect(this.currentScreenId).to.equal('create-event');\n const source = this.getRenderedText();\n // CreateEventScreen.tsx has: showDuplicateWarning logic and \"Événement similaire détecté\" warning\n expect(/showDuplicateWarning/.test(source), 'Form should have duplicate detection logic').to.be.true;\n expect(/Événement similaire détecté/.test(source), 'Form should have duplicate warning message').to.be.true;\n});",
|
||||
"lineNumber": 64
|
||||
},
|
||||
{
|
||||
"pattern": "le formulaire permet d'importer depuis Mobilizon ou Transiscope",
|
||||
"keyword": "Then",
|
||||
"file": "form.steps.ts",
|
||||
"sourceCode": "Then('le formulaire permet d\\'importer depuis Mobilizon ou Transiscope', async function (this: FestipodWorld) {\n expect(this.currentScreenId).to.equal('create-event');\n const source = this.getRenderedText();\n // CreateEventScreen.tsx has: importableEvents with Mobilizon and Transiscope sources\n expect(/importableEvents/.test(source), 'Form should have importable events data').to.be.true;\n expect(/Mobilizon/.test(source), 'Form should support Mobilizon import').to.be.true;\n expect(/Transiscope/.test(source), 'Form should support Transiscope import').to.be.true;\n expect(/Importer depuis une source externe/.test(source), 'Form should have import section').to.be.true;\n});",
|
||||
"lineNumber": 72
|
||||
},
|
||||
{
|
||||
"pattern": "l'import externe ne déclenche pas d'alerte doublon",
|
||||
"keyword": "Then",
|
||||
"file": "form.steps.ts",
|
||||
"sourceCode": "Then('l\\'import externe ne déclenche pas d\\'alerte doublon', async function (this: FestipodWorld) {\n expect(this.currentScreenId).to.equal('create-event');\n const source = this.getRenderedText();\n // CreateEventScreen.tsx has: importedFrom state and !importedFrom in showDuplicateWarning condition\n expect(/importedFrom/.test(source), 'Form should track import source').to.be.true;\n expect(/&& !importedFrom/.test(source), 'Duplicate warning should be disabled for imports').to.be.true;\n});",
|
||||
"lineNumber": 82
|
||||
},
|
||||
{
|
||||
"pattern": "je peux voir la liste des participants",
|
||||
"keyword": "Then",
|
||||
@@ -325,12 +346,19 @@ export const stepDefinitions: StepDefinitionInfo[] = [
|
||||
"sourceCode": "Then('je peux voir les événements auxquels l\\'utilisateur a participé', async function (this: FestipodWorld) {\n expect(this.currentScreenId).to.equal('user-profile');\n const source = this.getRenderedText();\n // UserProfileScreen.tsx: \"Événements à venir\" and \"Événements passés\" sections\n expect(/Événements à venir/.test(source), 'User profile should have \"Événements à venir\" section').to.be.true;\n expect(/Événements passés/.test(source), 'User profile should have \"Événements passés\" section').to.be.true;\n});",
|
||||
"lineNumber": 175
|
||||
},
|
||||
{
|
||||
"pattern": "les événements affichent leur localisation et distance",
|
||||
"keyword": "Then",
|
||||
"file": "screen.steps.ts",
|
||||
"sourceCode": "Then('les événements affichent leur localisation et distance', async function (this: FestipodWorld) {\n expect(this.currentScreenId).to.equal('user-profile');\n const source = this.getRenderedText();\n // UserProfileScreen.tsx: events have location and distance in data\n expect(/location: '[^']+'/.test(source), 'Events should have location data').to.be.true;\n expect(/distance: \\d+/.test(source), 'Events should have distance data').to.be.true;\n // Verify location is rendered in template\n expect(/\\{event\\.location\\}/.test(source), 'Events should render location').to.be.true;\n expect(/\\{event\\.distance\\}/.test(source), 'Events should render distance').to.be.true;\n});",
|
||||
"lineNumber": 183
|
||||
},
|
||||
{
|
||||
"pattern": "je peux configurer mes notifications",
|
||||
"keyword": "Then",
|
||||
"file": "screen.steps.ts",
|
||||
"sourceCode": "Then('je peux configurer mes notifications', async function (this: FestipodWorld) {\n expect(this.currentScreenId).to.equal('settings');\n const source = this.getRenderedText();\n // SettingsScreen.tsx line 25: <Text>Notifications</Text> with Toggle\n expect(/>Notifications</.test(source), 'Settings should have \"Notifications\" text').to.be.true;\n expect(/<Toggle[^>]*checked=\\{notifications\\}/.test(source), 'Settings should have Toggle for notifications').to.be.true;\n});",
|
||||
"lineNumber": 183
|
||||
"lineNumber": 194
|
||||
}
|
||||
];
|
||||
|
||||
|
||||
+46
-30
@@ -15,11 +15,11 @@ interface RawFeatureTestStatus {
|
||||
const rawResults: RawFeatureTestStatus[] = [
|
||||
{
|
||||
"featureId": "us-13",
|
||||
"totalScenarios": 7,
|
||||
"passed": 4,
|
||||
"totalScenarios": 10,
|
||||
"passed": 7,
|
||||
"failed": 0,
|
||||
"skipped": 3,
|
||||
"lastRun": "2026-01-26T17:08:25.769Z",
|
||||
"lastRun": "2026-01-26T17:31:35.878Z",
|
||||
"scenarios": [
|
||||
{
|
||||
"name": "Accéder au formulaire de relai d'événement",
|
||||
@@ -37,6 +37,18 @@ const rawResults: RawFeatureTestStatus[] = [
|
||||
"name": "Pouvoir annuler le relai d'événement",
|
||||
"status": "passed"
|
||||
},
|
||||
{
|
||||
"name": "Détecter un événement similaire déjà relayé",
|
||||
"status": "passed"
|
||||
},
|
||||
{
|
||||
"name": "Importer un événement depuis une source externe",
|
||||
"status": "passed"
|
||||
},
|
||||
{
|
||||
"name": "Pas d'alerte doublon lors d'un import externe",
|
||||
"status": "passed"
|
||||
},
|
||||
{
|
||||
"name": "Modifier un événement",
|
||||
"status": "skipped"
|
||||
@@ -57,7 +69,7 @@ const rawResults: RawFeatureTestStatus[] = [
|
||||
"passed": 3,
|
||||
"failed": 0,
|
||||
"skipped": 0,
|
||||
"lastRun": "2026-01-26T17:08:25.769Z",
|
||||
"lastRun": "2026-01-26T17:31:35.878Z",
|
||||
"scenarios": [
|
||||
{
|
||||
"name": "Accéder aux détails d'un événement terminé",
|
||||
@@ -79,7 +91,7 @@ const rawResults: RawFeatureTestStatus[] = [
|
||||
"passed": 0,
|
||||
"failed": 0,
|
||||
"skipped": 5,
|
||||
"lastRun": "2026-01-26T17:08:25.769Z",
|
||||
"lastRun": "2026-01-26T17:31:35.878Z",
|
||||
"scenarios": [
|
||||
{
|
||||
"name": "Voir les commentaires existants",
|
||||
@@ -109,7 +121,7 @@ const rawResults: RawFeatureTestStatus[] = [
|
||||
"passed": 2,
|
||||
"failed": 0,
|
||||
"skipped": 4,
|
||||
"lastRun": "2026-01-26T17:08:25.769Z",
|
||||
"lastRun": "2026-01-26T17:31:35.878Z",
|
||||
"scenarios": [
|
||||
{
|
||||
"name": "Consulter un événement avant inscription",
|
||||
@@ -143,7 +155,7 @@ const rawResults: RawFeatureTestStatus[] = [
|
||||
"passed": 0,
|
||||
"failed": 0,
|
||||
"skipped": 8,
|
||||
"lastRun": "2026-01-26T17:08:25.769Z",
|
||||
"lastRun": "2026-01-26T17:31:35.879Z",
|
||||
"scenarios": [
|
||||
{
|
||||
"name": "Consulter un macro-événement",
|
||||
@@ -185,7 +197,7 @@ const rawResults: RawFeatureTestStatus[] = [
|
||||
"passed": 4,
|
||||
"failed": 0,
|
||||
"skipped": 0,
|
||||
"lastRun": "2026-01-26T17:08:25.769Z",
|
||||
"lastRun": "2026-01-26T17:31:35.879Z",
|
||||
"scenarios": [
|
||||
{
|
||||
"name": "Accéder aux points de rencontre",
|
||||
@@ -211,7 +223,7 @@ const rawResults: RawFeatureTestStatus[] = [
|
||||
"passed": 0,
|
||||
"failed": 0,
|
||||
"skipped": 5,
|
||||
"lastRun": "2026-01-26T17:08:25.769Z",
|
||||
"lastRun": "2026-01-26T17:31:35.879Z",
|
||||
"scenarios": [
|
||||
{
|
||||
"name": "Partager un événement auquel je participe",
|
||||
@@ -241,7 +253,7 @@ const rawResults: RawFeatureTestStatus[] = [
|
||||
"passed": 1,
|
||||
"failed": 0,
|
||||
"skipped": 3,
|
||||
"lastRun": "2026-01-26T17:08:25.770Z",
|
||||
"lastRun": "2026-01-26T17:31:35.879Z",
|
||||
"scenarios": [
|
||||
{
|
||||
"name": "Configurer les notifications de nouveaux participants",
|
||||
@@ -267,7 +279,7 @@ const rawResults: RawFeatureTestStatus[] = [
|
||||
"passed": 3,
|
||||
"failed": 0,
|
||||
"skipped": 2,
|
||||
"lastRun": "2026-01-26T17:08:25.770Z",
|
||||
"lastRun": "2026-01-26T17:31:35.879Z",
|
||||
"scenarios": [
|
||||
{
|
||||
"name": "Voir les événements à venir sur l'accueil",
|
||||
@@ -293,11 +305,11 @@ const rawResults: RawFeatureTestStatus[] = [
|
||||
},
|
||||
{
|
||||
"featureId": "us-10",
|
||||
"totalScenarios": 5,
|
||||
"passed": 4,
|
||||
"totalScenarios": 6,
|
||||
"passed": 5,
|
||||
"failed": 0,
|
||||
"skipped": 1,
|
||||
"lastRun": "2026-01-26T17:08:25.770Z",
|
||||
"lastRun": "2026-01-26T17:31:35.879Z",
|
||||
"scenarios": [
|
||||
{
|
||||
"name": "Accéder au profil d'un participant",
|
||||
@@ -307,6 +319,10 @@ const rawResults: RawFeatureTestStatus[] = [
|
||||
"name": "Voir les événements du participant",
|
||||
"status": "passed"
|
||||
},
|
||||
{
|
||||
"name": "Voir la localisation des événements",
|
||||
"status": "passed"
|
||||
},
|
||||
{
|
||||
"name": "Voir le formulaire de contact",
|
||||
"status": "passed"
|
||||
@@ -327,7 +343,7 @@ const rawResults: RawFeatureTestStatus[] = [
|
||||
"passed": 3,
|
||||
"failed": 0,
|
||||
"skipped": 4,
|
||||
"lastRun": "2026-01-26T17:08:25.770Z",
|
||||
"lastRun": "2026-01-26T17:31:35.879Z",
|
||||
"scenarios": [
|
||||
{
|
||||
"name": "Accéder à la liste des événements depuis le profil",
|
||||
@@ -365,7 +381,7 @@ const rawResults: RawFeatureTestStatus[] = [
|
||||
"passed": 3,
|
||||
"failed": 0,
|
||||
"skipped": 2,
|
||||
"lastRun": "2026-01-26T17:08:25.770Z",
|
||||
"lastRun": "2026-01-26T17:31:35.879Z",
|
||||
"scenarios": [
|
||||
{
|
||||
"name": "Accéder à la liste des inscrits d'un événement",
|
||||
@@ -395,7 +411,7 @@ const rawResults: RawFeatureTestStatus[] = [
|
||||
"passed": 5,
|
||||
"failed": 0,
|
||||
"skipped": 1,
|
||||
"lastRun": "2026-01-26T17:08:25.770Z",
|
||||
"lastRun": "2026-01-26T17:31:35.879Z",
|
||||
"scenarios": [
|
||||
{
|
||||
"name": "Accéder à mon profil",
|
||||
@@ -429,7 +445,7 @@ const rawResults: RawFeatureTestStatus[] = [
|
||||
"passed": 2,
|
||||
"failed": 0,
|
||||
"skipped": 3,
|
||||
"lastRun": "2026-01-26T17:08:25.770Z",
|
||||
"lastRun": "2026-01-26T17:31:35.879Z",
|
||||
"scenarios": [
|
||||
{
|
||||
"name": "Accéder aux paramètres de profil",
|
||||
@@ -459,7 +475,7 @@ const rawResults: RawFeatureTestStatus[] = [
|
||||
"passed": 5,
|
||||
"failed": 0,
|
||||
"skipped": 0,
|
||||
"lastRun": "2026-01-26T17:08:25.770Z",
|
||||
"lastRun": "2026-01-26T17:31:35.879Z",
|
||||
"scenarios": [
|
||||
{
|
||||
"name": "Accéder au partage de profil",
|
||||
@@ -489,7 +505,7 @@ const rawResults: RawFeatureTestStatus[] = [
|
||||
"passed": 5,
|
||||
"failed": 0,
|
||||
"skipped": 0,
|
||||
"lastRun": "2026-01-26T17:08:25.770Z",
|
||||
"lastRun": "2026-01-26T17:31:35.879Z",
|
||||
"scenarios": [
|
||||
{
|
||||
"name": "Accéder au partage depuis le profil",
|
||||
@@ -519,7 +535,7 @@ const rawResults: RawFeatureTestStatus[] = [
|
||||
"passed": 2,
|
||||
"failed": 0,
|
||||
"skipped": 1,
|
||||
"lastRun": "2026-01-26T17:08:25.770Z",
|
||||
"lastRun": "2026-01-26T17:31:35.879Z",
|
||||
"scenarios": [
|
||||
{
|
||||
"name": "Accéder aux paramètres de notification",
|
||||
@@ -541,7 +557,7 @@ const rawResults: RawFeatureTestStatus[] = [
|
||||
"passed": 1,
|
||||
"failed": 0,
|
||||
"skipped": 2,
|
||||
"lastRun": "2026-01-26T17:08:25.770Z",
|
||||
"lastRun": "2026-01-26T17:31:35.879Z",
|
||||
"scenarios": [
|
||||
{
|
||||
"name": "Accéder aux paramètres de notification",
|
||||
@@ -563,7 +579,7 @@ const rawResults: RawFeatureTestStatus[] = [
|
||||
"passed": 3,
|
||||
"failed": 0,
|
||||
"skipped": 1,
|
||||
"lastRun": "2026-01-26T17:08:25.770Z",
|
||||
"lastRun": "2026-01-26T17:31:35.879Z",
|
||||
"scenarios": [
|
||||
{
|
||||
"name": "Accéder au formulaire de relai d'événement",
|
||||
@@ -589,7 +605,7 @@ const rawResults: RawFeatureTestStatus[] = [
|
||||
"passed": 4,
|
||||
"failed": 0,
|
||||
"skipped": 1,
|
||||
"lastRun": "2026-01-26T17:08:25.770Z",
|
||||
"lastRun": "2026-01-26T17:31:35.879Z",
|
||||
"scenarios": [
|
||||
{
|
||||
"name": "Accéder au profil pour voir la photo",
|
||||
@@ -619,7 +635,7 @@ const rawResults: RawFeatureTestStatus[] = [
|
||||
"passed": 0,
|
||||
"failed": 0,
|
||||
"skipped": 5,
|
||||
"lastRun": "2026-01-26T17:08:25.770Z",
|
||||
"lastRun": "2026-01-26T17:31:35.879Z",
|
||||
"scenarios": [
|
||||
{
|
||||
"name": "Accéder aux détails d'un événement terminé",
|
||||
@@ -649,7 +665,7 @@ const rawResults: RawFeatureTestStatus[] = [
|
||||
"passed": 0,
|
||||
"failed": 0,
|
||||
"skipped": 3,
|
||||
"lastRun": "2026-01-26T17:08:25.770Z",
|
||||
"lastRun": "2026-01-26T17:31:35.879Z",
|
||||
"scenarios": [
|
||||
{
|
||||
"name": "Accéder au bilan consolidé",
|
||||
@@ -671,7 +687,7 @@ const rawResults: RawFeatureTestStatus[] = [
|
||||
"passed": 0,
|
||||
"failed": 0,
|
||||
"skipped": 7,
|
||||
"lastRun": "2026-01-26T17:08:25.770Z",
|
||||
"lastRun": "2026-01-26T17:31:35.879Z",
|
||||
"scenarios": [
|
||||
{
|
||||
"name": "Accéder à la création d'atelier",
|
||||
@@ -709,7 +725,7 @@ const rawResults: RawFeatureTestStatus[] = [
|
||||
"passed": 0,
|
||||
"failed": 0,
|
||||
"skipped": 5,
|
||||
"lastRun": "2026-01-26T17:08:25.770Z",
|
||||
"lastRun": "2026-01-26T17:31:35.879Z",
|
||||
"scenarios": [
|
||||
{
|
||||
"name": "Accéder à la zone de notes personnelles",
|
||||
@@ -739,7 +755,7 @@ const rawResults: RawFeatureTestStatus[] = [
|
||||
"passed": 0,
|
||||
"failed": 0,
|
||||
"skipped": 5,
|
||||
"lastRun": "2026-01-26T17:08:25.770Z",
|
||||
"lastRun": "2026-01-26T17:31:35.879Z",
|
||||
"scenarios": [
|
||||
{
|
||||
"name": "Voir les commentaires existants d'un atelier",
|
||||
@@ -769,7 +785,7 @@ const rawResults: RawFeatureTestStatus[] = [
|
||||
"passed": 0,
|
||||
"failed": 0,
|
||||
"skipped": 4,
|
||||
"lastRun": "2026-01-26T17:08:25.770Z",
|
||||
"lastRun": "2026-01-26T17:31:35.879Z",
|
||||
"scenarios": [
|
||||
{
|
||||
"name": "Voir les ateliers d'un événement",
|
||||
|
||||
@@ -2,14 +2,38 @@ import React, { useState } from 'react';
|
||||
import { Header, Text, Input, Button, Placeholder } from '../components/sketchy';
|
||||
import type { ScreenProps } from './index';
|
||||
|
||||
// Demo data for suggestions
|
||||
const existingEvents = [
|
||||
{ name: 'Résidence Reconnexion', relayedBy: 'Thomas Martin' },
|
||||
];
|
||||
|
||||
const importableEvents = [
|
||||
{
|
||||
name: 'Festival des Utopies Concrètes',
|
||||
source: 'Mobilizon',
|
||||
date: '2026-03-15',
|
||||
location: 'Paris, Parc de la Villette',
|
||||
description: 'Festival annuel présentant des alternatives concrètes pour un monde durable.',
|
||||
},
|
||||
{
|
||||
name: 'Rencontres de l\'Écologie',
|
||||
source: 'Transiscope',
|
||||
date: '2026-04-20',
|
||||
location: 'Lyon, Halle Tony Garnier',
|
||||
description: 'Deux jours de conférences et ateliers sur la transition écologique.',
|
||||
},
|
||||
];
|
||||
|
||||
export function CreateEventScreen({ navigate }: ScreenProps) {
|
||||
const [name, setName] = useState('');
|
||||
const [startDate, setStartDate] = useState('');
|
||||
const [location, setLocation] = useState('');
|
||||
const [description, setDescription] = useState('');
|
||||
const [showSuggestions, setShowSuggestions] = useState(false);
|
||||
const [importedFrom, setImportedFrom] = useState<string | null>(null);
|
||||
|
||||
// Show warning only when key fields are filled
|
||||
const showDuplicateWarning = name.length > 3 && startDate && location.length > 3;
|
||||
// Show warning only when key fields are filled AND not imported from external source
|
||||
const showDuplicateWarning = name.length > 3 && startDate && location.length > 3 && !importedFrom;
|
||||
|
||||
return (
|
||||
<div style={{ display: 'flex', flexDirection: 'column', height: '100%' }}>
|
||||
@@ -53,13 +77,93 @@ export function CreateEventScreen({ navigate }: ScreenProps) {
|
||||
)}
|
||||
|
||||
<div style={{ display: 'flex', flexDirection: 'column', gap: 16 }}>
|
||||
<div>
|
||||
<div style={{ position: 'relative' }}>
|
||||
<Text style={{ marginBottom: 6, fontSize: 14 }}>Nom de l'événement *</Text>
|
||||
<Input
|
||||
placeholder="Donnez un nom à votre événement"
|
||||
value={name}
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => setName(e.target.value)}
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setName(e.target.value);
|
||||
setShowSuggestions(e.target.value.length > 0);
|
||||
setImportedFrom(null); // Reset import flag when user types manually
|
||||
}}
|
||||
onFocus={() => name.length > 0 && setShowSuggestions(true)}
|
||||
onBlur={() => setTimeout(() => setShowSuggestions(false), 200)}
|
||||
/>
|
||||
|
||||
{/* Suggestions dropdown */}
|
||||
{showSuggestions && (
|
||||
<div style={{
|
||||
position: 'absolute',
|
||||
top: '100%',
|
||||
left: 0,
|
||||
right: 0,
|
||||
background: 'white',
|
||||
border: '2px solid var(--sketch-black)',
|
||||
borderRadius: 8,
|
||||
marginTop: 4,
|
||||
zIndex: 10,
|
||||
maxHeight: 250,
|
||||
overflow: 'auto',
|
||||
}}>
|
||||
{/* Existing events - not selectable */}
|
||||
{existingEvents.length > 0 && (
|
||||
<>
|
||||
<div style={{ padding: '8px 12px', background: 'var(--sketch-light-gray)', fontSize: 12, fontWeight: 'bold' }}>
|
||||
Déjà relayé sur Festipod
|
||||
</div>
|
||||
{existingEvents.map((event, i) => (
|
||||
<div
|
||||
key={`existing-${i}`}
|
||||
style={{
|
||||
padding: '10px 12px',
|
||||
borderBottom: '1px solid var(--sketch-light-gray)',
|
||||
opacity: 0.6,
|
||||
cursor: 'not-allowed',
|
||||
}}
|
||||
>
|
||||
<Text style={{ margin: 0, fontSize: 14 }}>{event.name}</Text>
|
||||
<Text style={{ margin: '2px 0 0 0', fontSize: 12, color: 'var(--sketch-gray)' }}>
|
||||
Relayé par {event.relayedBy}
|
||||
</Text>
|
||||
</div>
|
||||
))}
|
||||
</>
|
||||
)}
|
||||
|
||||
{/* Importable events */}
|
||||
{importableEvents.length > 0 && (
|
||||
<>
|
||||
<div style={{ padding: '8px 12px', background: 'var(--sketch-light-gray)', fontSize: 12, fontWeight: 'bold' }}>
|
||||
Importer depuis une source externe
|
||||
</div>
|
||||
{importableEvents.map((event, i) => (
|
||||
<div
|
||||
key={`import-${i}`}
|
||||
style={{
|
||||
padding: '10px 12px',
|
||||
borderBottom: '1px solid var(--sketch-light-gray)',
|
||||
cursor: 'pointer',
|
||||
}}
|
||||
onClick={() => {
|
||||
setName(event.name);
|
||||
setStartDate(event.date);
|
||||
setLocation(event.location);
|
||||
setDescription(event.description);
|
||||
setImportedFrom(event.source);
|
||||
setShowSuggestions(false);
|
||||
}}
|
||||
>
|
||||
<Text style={{ margin: 0, fontSize: 14 }}>{event.name}</Text>
|
||||
<Text style={{ margin: '2px 0 0 0', fontSize: 12, color: 'var(--sketch-gray)' }}>
|
||||
via {event.source} · {event.location}
|
||||
</Text>
|
||||
</div>
|
||||
))}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div style={{ display: 'flex', gap: 12 }}>
|
||||
|
||||
@@ -39,6 +39,7 @@ export function EventDetailScreen({ navigate }: ScreenProps) {
|
||||
</Text>
|
||||
<Text style={{ margin: 0, fontSize: 15 }}>
|
||||
📍 <span className="user-content">Le Revel, Rogues (30)</span>
|
||||
<span style={{ color: 'var(--sketch-gray)' }}> · 142 km</span>
|
||||
</Text>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -2,10 +2,11 @@ import React from 'react';
|
||||
import { Header, Input, Card, Text, Badge, NavBar } from '../components/sketchy';
|
||||
import type { ScreenProps } from './index';
|
||||
|
||||
function EventCard({ title, date, location, attendees, onClick }: {
|
||||
function EventCard({ title, date, location, distance, attendees, onClick }: {
|
||||
title: string;
|
||||
date: string;
|
||||
location: string;
|
||||
distance: number;
|
||||
attendees: number;
|
||||
onClick: () => void;
|
||||
}) {
|
||||
@@ -17,6 +18,7 @@ function EventCard({ title, date, location, attendees, onClick }: {
|
||||
</Text>
|
||||
<Text style={{ margin: '0 0 8px 0', fontSize: 14 }}>
|
||||
📍 <span className="user-content">{location}</span>
|
||||
<span style={{ color: 'var(--sketch-gray)' }}> · {distance} km</span>
|
||||
</Text>
|
||||
<Badge>{attendees} inscrits</Badge>
|
||||
</Card>
|
||||
@@ -68,6 +70,7 @@ export function EventsScreen({ navigate }: ScreenProps) {
|
||||
title="Résidence Reconnexion"
|
||||
date="Lun. 16 - Ven. 20 fév."
|
||||
location="Le Revel, Rogues (30)"
|
||||
distance={142}
|
||||
attendees={24}
|
||||
onClick={() => navigate('event-detail')}
|
||||
/>
|
||||
@@ -75,6 +78,7 @@ export function EventsScreen({ navigate }: ScreenProps) {
|
||||
title="Atelier low-tech"
|
||||
date="Sam. 8 fév. · 14h00"
|
||||
location="La Maison du Vélo, Lyon"
|
||||
distance={3}
|
||||
attendees={12}
|
||||
onClick={() => navigate('event-detail')}
|
||||
/>
|
||||
@@ -82,6 +86,7 @@ export function EventsScreen({ navigate }: ScreenProps) {
|
||||
title="Forum Ouvert Transition"
|
||||
date="Sam. 22 fév. · 9h00"
|
||||
location="Tiers-lieu L'Hermitage"
|
||||
distance={89}
|
||||
attendees={45}
|
||||
onClick={() => navigate('event-detail')}
|
||||
/>
|
||||
@@ -89,6 +94,7 @@ export function EventsScreen({ navigate }: ScreenProps) {
|
||||
title="Formation CNV"
|
||||
date="Sam. 1 mars · 9h30"
|
||||
location="MJC Montplaisir, Lyon"
|
||||
distance={5}
|
||||
attendees={16}
|
||||
onClick={() => navigate('event-detail')}
|
||||
/>
|
||||
@@ -96,6 +102,7 @@ export function EventsScreen({ navigate }: ScreenProps) {
|
||||
title="Rencontre des Colibris"
|
||||
date="Mer. 12 fév. · 19h00"
|
||||
location="La Maison de l'Environnement"
|
||||
distance={7}
|
||||
attendees={30}
|
||||
onClick={() => navigate('event-detail')}
|
||||
/>
|
||||
|
||||
@@ -2,14 +2,17 @@ import React from 'react';
|
||||
import { Button, Title, Text, Card, NavBar, Badge } from '../components/sketchy';
|
||||
import type { ScreenProps } from './index';
|
||||
|
||||
function EventCard({ title, date, location, attendees, onClick }: { title: string; date: string; location: string; attendees: number; onClick: () => void }) {
|
||||
function EventCard({ title, date, location, distance, attendees, onClick }: { title: string; date: string; location: string; distance: number; attendees: number; onClick: () => void }) {
|
||||
return (
|
||||
<Card onClick={onClick} style={{ marginBottom: 12 }}>
|
||||
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start' }}>
|
||||
<div>
|
||||
<Text className="user-content" style={{ margin: 0, fontWeight: 'bold' }}>{title}</Text>
|
||||
<Text className="user-content" style={{ margin: '4px 0 0 0', fontSize: 14 }}>{date}</Text>
|
||||
<Text style={{ margin: '2px 0 0 0', fontSize: 14 }}>📍 <span className="user-content">{location}</span></Text>
|
||||
<Text style={{ margin: '2px 0 0 0', fontSize: 14 }}>
|
||||
📍 <span className="user-content">{location}</span>
|
||||
<span style={{ color: 'var(--sketch-gray)' }}> · {distance} km</span>
|
||||
</Text>
|
||||
</div>
|
||||
<Badge>{attendees} inscrits</Badge>
|
||||
</div>
|
||||
@@ -57,6 +60,7 @@ export function HomeScreen({ navigate }: ScreenProps) {
|
||||
title="Résidence Reconnexion"
|
||||
date="Lun. 16 - Ven. 20 fév."
|
||||
location="Le Revel, Rogues (30)"
|
||||
distance={142}
|
||||
attendees={24}
|
||||
onClick={() => navigate('event-detail')}
|
||||
/>
|
||||
@@ -64,6 +68,7 @@ export function HomeScreen({ navigate }: ScreenProps) {
|
||||
title="Atelier low-tech"
|
||||
date="Sam. 8 fév. · 14h00"
|
||||
location="La Maison du Vélo, Lyon"
|
||||
distance={3}
|
||||
attendees={12}
|
||||
onClick={() => navigate('event-detail')}
|
||||
/>
|
||||
@@ -71,6 +76,7 @@ export function HomeScreen({ navigate }: ScreenProps) {
|
||||
title="Forum Ouvert Transition"
|
||||
date="Sam. 22 fév. · 9h00"
|
||||
location="Tiers-lieu L'Hermitage"
|
||||
distance={89}
|
||||
attendees={45}
|
||||
onClick={() => navigate('event-detail')}
|
||||
/>
|
||||
|
||||
@@ -4,15 +4,15 @@ import type { ScreenProps } from './index';
|
||||
|
||||
export function UserProfileScreen({ navigate }: ScreenProps) {
|
||||
const upcomingEvents = [
|
||||
{ title: 'Résidence Reconnexion', date: '16-20 fév.', common: true },
|
||||
{ title: 'Atelier permaculture', date: '28 fév.', common: false },
|
||||
{ title: 'Résidence Reconnexion', date: '16-20 fév.', location: 'Le Revel, Rogues (30)', distance: 142, common: true },
|
||||
{ title: 'Atelier permaculture', date: '28 fév.', location: 'Ferme des Music, Vénissieux', distance: 12, common: false },
|
||||
];
|
||||
|
||||
const pastEvents = [
|
||||
{ title: 'Forum Ouvert Transition', date: '22 jan.', common: true },
|
||||
{ title: 'Rencontre des Colibris', date: '12 jan.', common: true },
|
||||
{ title: 'Formation CNV', date: '8 jan.', common: false },
|
||||
{ title: 'Café des possibles', date: '15 déc.', common: false },
|
||||
{ title: 'Forum Ouvert Transition', date: '22 jan.', location: 'Tiers-lieu L\'Hermitage', distance: 89, common: true },
|
||||
{ title: 'Rencontre des Colibris', date: '12 jan.', location: 'La Maison de l\'Environnement', distance: 7, common: true },
|
||||
{ title: 'Formation CNV', date: '8 jan.', location: 'MJC Montplaisir, Lyon', distance: 5, common: false },
|
||||
{ title: 'Café des possibles', date: '15 déc.', location: 'Café de la Mairie, Lyon 3', distance: 2, common: false },
|
||||
];
|
||||
|
||||
return (
|
||||
@@ -65,6 +65,10 @@ export function UserProfileScreen({ navigate }: ScreenProps) {
|
||||
<Text className="user-content" style={{ margin: '4px 0 0 0', fontSize: 14 }}>
|
||||
{event.date}
|
||||
</Text>
|
||||
<Text style={{ margin: '2px 0 0 0', fontSize: 14 }}>
|
||||
📍 <span className="user-content">{event.location}</span>
|
||||
<span style={{ color: 'var(--sketch-gray)' }}> · {event.distance} km</span>
|
||||
</Text>
|
||||
</div>
|
||||
{event.common && <Badge>moi aussi</Badge>}
|
||||
</div>
|
||||
@@ -86,6 +90,10 @@ export function UserProfileScreen({ navigate }: ScreenProps) {
|
||||
<Text className="user-content" style={{ margin: '4px 0 0 0', fontSize: 14 }}>
|
||||
{event.date}
|
||||
</Text>
|
||||
<Text style={{ margin: '2px 0 0 0', fontSize: 14 }}>
|
||||
📍 <span className="user-content">{event.location}</span>
|
||||
<span style={{ color: 'var(--sketch-gray)' }}> · {event.distance} km</span>
|
||||
</Text>
|
||||
</div>
|
||||
{event.common && <Badge>moi aussi</Badge>}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user