Warning if similar event exists

This commit is contained in:
Sylvain Duchesne
2026-01-26 18:12:34 +01:00
parent 2415409374
commit b7f86b139f
9 changed files with 765 additions and 627 deletions
+26 -26
View File
@@ -19,7 +19,7 @@ const rawResults: RawFeatureTestStatus[] = [
"passed": 4,
"failed": 0,
"skipped": 3,
"lastRun": "2026-01-26T16:42:34.763Z",
"lastRun": "2026-01-26T17:08:25.769Z",
"scenarios": [
{
"name": "Accéder au formulaire de relai d'événement",
@@ -57,7 +57,7 @@ const rawResults: RawFeatureTestStatus[] = [
"passed": 3,
"failed": 0,
"skipped": 0,
"lastRun": "2026-01-26T16:42:34.763Z",
"lastRun": "2026-01-26T17:08:25.769Z",
"scenarios": [
{
"name": "Accéder aux détails d'un événement terminé",
@@ -79,7 +79,7 @@ const rawResults: RawFeatureTestStatus[] = [
"passed": 0,
"failed": 0,
"skipped": 5,
"lastRun": "2026-01-26T16:42:34.763Z",
"lastRun": "2026-01-26T17:08:25.769Z",
"scenarios": [
{
"name": "Voir les commentaires existants",
@@ -109,7 +109,7 @@ const rawResults: RawFeatureTestStatus[] = [
"passed": 2,
"failed": 0,
"skipped": 4,
"lastRun": "2026-01-26T16:42:34.763Z",
"lastRun": "2026-01-26T17:08:25.769Z",
"scenarios": [
{
"name": "Consulter un événement avant inscription",
@@ -143,7 +143,7 @@ const rawResults: RawFeatureTestStatus[] = [
"passed": 0,
"failed": 0,
"skipped": 8,
"lastRun": "2026-01-26T16:42:34.763Z",
"lastRun": "2026-01-26T17:08:25.769Z",
"scenarios": [
{
"name": "Consulter un macro-événement",
@@ -185,7 +185,7 @@ const rawResults: RawFeatureTestStatus[] = [
"passed": 4,
"failed": 0,
"skipped": 0,
"lastRun": "2026-01-26T16:42:34.763Z",
"lastRun": "2026-01-26T17:08:25.769Z",
"scenarios": [
{
"name": "Accéder aux points de rencontre",
@@ -211,7 +211,7 @@ const rawResults: RawFeatureTestStatus[] = [
"passed": 0,
"failed": 0,
"skipped": 5,
"lastRun": "2026-01-26T16:42:34.763Z",
"lastRun": "2026-01-26T17:08:25.769Z",
"scenarios": [
{
"name": "Partager un événement auquel je participe",
@@ -241,7 +241,7 @@ const rawResults: RawFeatureTestStatus[] = [
"passed": 1,
"failed": 0,
"skipped": 3,
"lastRun": "2026-01-26T16:42:34.763Z",
"lastRun": "2026-01-26T17:08:25.770Z",
"scenarios": [
{
"name": "Configurer les notifications de nouveaux participants",
@@ -267,7 +267,7 @@ const rawResults: RawFeatureTestStatus[] = [
"passed": 3,
"failed": 0,
"skipped": 2,
"lastRun": "2026-01-26T16:42:34.763Z",
"lastRun": "2026-01-26T17:08:25.770Z",
"scenarios": [
{
"name": "Voir les événements à venir sur l'accueil",
@@ -297,7 +297,7 @@ const rawResults: RawFeatureTestStatus[] = [
"passed": 4,
"failed": 0,
"skipped": 1,
"lastRun": "2026-01-26T16:42:34.763Z",
"lastRun": "2026-01-26T17:08:25.770Z",
"scenarios": [
{
"name": "Accéder au profil d'un participant",
@@ -327,7 +327,7 @@ const rawResults: RawFeatureTestStatus[] = [
"passed": 3,
"failed": 0,
"skipped": 4,
"lastRun": "2026-01-26T16:42:34.763Z",
"lastRun": "2026-01-26T17:08:25.770Z",
"scenarios": [
{
"name": "Accéder à la liste des événements depuis le profil",
@@ -365,7 +365,7 @@ const rawResults: RawFeatureTestStatus[] = [
"passed": 3,
"failed": 0,
"skipped": 2,
"lastRun": "2026-01-26T16:42:34.763Z",
"lastRun": "2026-01-26T17:08:25.770Z",
"scenarios": [
{
"name": "Accéder à la liste des inscrits d'un événement",
@@ -395,7 +395,7 @@ const rawResults: RawFeatureTestStatus[] = [
"passed": 5,
"failed": 0,
"skipped": 1,
"lastRun": "2026-01-26T16:42:34.763Z",
"lastRun": "2026-01-26T17:08:25.770Z",
"scenarios": [
{
"name": "Accéder à mon profil",
@@ -429,7 +429,7 @@ const rawResults: RawFeatureTestStatus[] = [
"passed": 2,
"failed": 0,
"skipped": 3,
"lastRun": "2026-01-26T16:42:34.763Z",
"lastRun": "2026-01-26T17:08:25.770Z",
"scenarios": [
{
"name": "Accéder aux paramètres de profil",
@@ -459,7 +459,7 @@ const rawResults: RawFeatureTestStatus[] = [
"passed": 5,
"failed": 0,
"skipped": 0,
"lastRun": "2026-01-26T16:42:34.763Z",
"lastRun": "2026-01-26T17:08:25.770Z",
"scenarios": [
{
"name": "Accéder au partage de profil",
@@ -489,7 +489,7 @@ const rawResults: RawFeatureTestStatus[] = [
"passed": 5,
"failed": 0,
"skipped": 0,
"lastRun": "2026-01-26T16:42:34.763Z",
"lastRun": "2026-01-26T17:08:25.770Z",
"scenarios": [
{
"name": "Accéder au partage depuis le profil",
@@ -519,7 +519,7 @@ const rawResults: RawFeatureTestStatus[] = [
"passed": 2,
"failed": 0,
"skipped": 1,
"lastRun": "2026-01-26T16:42:34.763Z",
"lastRun": "2026-01-26T17:08:25.770Z",
"scenarios": [
{
"name": "Accéder aux paramètres de notification",
@@ -541,7 +541,7 @@ const rawResults: RawFeatureTestStatus[] = [
"passed": 1,
"failed": 0,
"skipped": 2,
"lastRun": "2026-01-26T16:42:34.763Z",
"lastRun": "2026-01-26T17:08:25.770Z",
"scenarios": [
{
"name": "Accéder aux paramètres de notification",
@@ -563,7 +563,7 @@ const rawResults: RawFeatureTestStatus[] = [
"passed": 3,
"failed": 0,
"skipped": 1,
"lastRun": "2026-01-26T16:42:34.763Z",
"lastRun": "2026-01-26T17:08:25.770Z",
"scenarios": [
{
"name": "Accéder au formulaire de relai d'événement",
@@ -589,7 +589,7 @@ const rawResults: RawFeatureTestStatus[] = [
"passed": 4,
"failed": 0,
"skipped": 1,
"lastRun": "2026-01-26T16:42:34.763Z",
"lastRun": "2026-01-26T17:08:25.770Z",
"scenarios": [
{
"name": "Accéder au profil pour voir la photo",
@@ -619,7 +619,7 @@ const rawResults: RawFeatureTestStatus[] = [
"passed": 0,
"failed": 0,
"skipped": 5,
"lastRun": "2026-01-26T16:42:34.763Z",
"lastRun": "2026-01-26T17:08:25.770Z",
"scenarios": [
{
"name": "Accéder aux détails d'un événement terminé",
@@ -649,7 +649,7 @@ const rawResults: RawFeatureTestStatus[] = [
"passed": 0,
"failed": 0,
"skipped": 3,
"lastRun": "2026-01-26T16:42:34.763Z",
"lastRun": "2026-01-26T17:08:25.770Z",
"scenarios": [
{
"name": "Accéder au bilan consolidé",
@@ -671,7 +671,7 @@ const rawResults: RawFeatureTestStatus[] = [
"passed": 0,
"failed": 0,
"skipped": 7,
"lastRun": "2026-01-26T16:42:34.764Z",
"lastRun": "2026-01-26T17:08:25.770Z",
"scenarios": [
{
"name": "Accéder à la création d'atelier",
@@ -709,7 +709,7 @@ const rawResults: RawFeatureTestStatus[] = [
"passed": 0,
"failed": 0,
"skipped": 5,
"lastRun": "2026-01-26T16:42:34.764Z",
"lastRun": "2026-01-26T17:08:25.770Z",
"scenarios": [
{
"name": "Accéder à la zone de notes personnelles",
@@ -739,7 +739,7 @@ const rawResults: RawFeatureTestStatus[] = [
"passed": 0,
"failed": 0,
"skipped": 5,
"lastRun": "2026-01-26T16:42:34.764Z",
"lastRun": "2026-01-26T17:08:25.770Z",
"scenarios": [
{
"name": "Voir les commentaires existants d'un atelier",
@@ -769,7 +769,7 @@ const rawResults: RawFeatureTestStatus[] = [
"passed": 0,
"failed": 0,
"skipped": 4,
"lastRun": "2026-01-26T16:42:34.764Z",
"lastRun": "2026-01-26T17:08:25.770Z",
"scenarios": [
{
"name": "Voir les ateliers d'un événement",
+71 -4
View File
@@ -1,8 +1,16 @@
import React from 'react';
import React, { useState } from 'react';
import { Header, Text, Input, Button, Placeholder } from '../components/sketchy';
import type { ScreenProps } from './index';
export function CreateEventScreen({ navigate }: ScreenProps) {
const [name, setName] = useState('');
const [startDate, setStartDate] = useState('');
const [location, setLocation] = useState('');
const [description, setDescription] = useState('');
// Show warning only when key fields are filled
const showDuplicateWarning = name.length > 3 && startDate && location.length > 3;
return (
<div style={{ display: 'flex', flexDirection: 'column', height: '100%' }}>
<Header
@@ -19,16 +27,50 @@ export function CreateEventScreen({ navigate }: ScreenProps) {
style={{ marginBottom: 20, cursor: 'pointer' }}
/>
{/* Duplicate warning - shown when key fields are filled */}
{showDuplicateWarning && (
<div style={{
background: '#FEF3C7',
border: '2px solid #F59E0B',
borderRadius: 8,
padding: 12,
marginBottom: 16,
}}>
<Text style={{ margin: 0, fontWeight: 'bold', fontSize: 14, marginBottom: 4 }}>
Événement similaire détecté
</Text>
<Text style={{ margin: 0, fontSize: 13, lineHeight: 1.5 }}>
Un événement similaire a déjà é relayé par <strong>Thomas Martin</strong>.
Vous pouvez continuer si vous pensez qu'il s'agit d'un événement différent.
</Text>
<Text
style={{ margin: '8px 0 0 0', fontSize: 13, cursor: 'pointer', textDecoration: 'underline' }}
onClick={() => navigate('event-detail')}
>
Voir l'événement existant
</Text>
</div>
)}
<div style={{ display: 'flex', flexDirection: 'column', gap: 16 }}>
<div>
<Text style={{ marginBottom: 6, fontSize: 14 }}>Nom de l'événement *</Text>
<Input placeholder="Donnez un nom à votre événement" />
<Input
placeholder="Donnez un nom à votre événement"
value={name}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => setName(e.target.value)}
/>
</div>
<div style={{ display: 'flex', gap: 12 }}>
<div style={{ flex: 1 }}>
<Text style={{ marginBottom: 6, fontSize: 14 }}>Date de début *</Text>
<Input type="date" placeholder="Début" />
<Input
type="date"
placeholder="Début"
value={startDate}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => setStartDate(e.target.value)}
/>
</div>
<div style={{ flex: 1 }}>
<Text style={{ marginBottom: 6, fontSize: 14 }}>Date de fin</Text>
@@ -49,7 +91,11 @@ export function CreateEventScreen({ navigate }: ScreenProps) {
<div>
<Text style={{ marginBottom: 6, fontSize: 14 }}>Lieu *</Text>
<Input placeholder="Ajouter un lieu" />
<Input
placeholder="Ajouter un lieu"
value={location}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => setLocation(e.target.value)}
/>
</div>
<div>
@@ -59,6 +105,8 @@ export function CreateEventScreen({ navigate }: ScreenProps) {
placeholder="Décrivez votre événement..."
rows={4}
style={{ resize: 'none' }}
value={description}
onChange={(e: React.ChangeEvent<HTMLTextAreaElement>) => setDescription(e.target.value)}
/>
</div>
@@ -91,6 +139,25 @@ export function CreateEventScreen({ navigate }: ScreenProps) {
{/* Footer */}
<div style={{ padding: 16, borderTop: '2px solid var(--sketch-black)' }}>
{showDuplicateWarning && (
<div style={{
background: '#FEF3C7',
border: '2px solid #F59E0B',
borderRadius: 8,
padding: 12,
marginBottom: 12,
}}>
<Text style={{ margin: 0, fontSize: 13, lineHeight: 1.5 }}>
Un événement similaire a déjà été relayé par <strong>Thomas Martin</strong>.{' '}
<span
style={{ cursor: 'pointer', textDecoration: 'underline' }}
onClick={() => navigate('event-detail')}
>
Voir →
</span>
</Text>
</div>
)}
<Button
variant="primary"
style={{ width: '100%' }}
+1 -1
View File
@@ -19,7 +19,7 @@ export function EventDetailScreen({ navigate }: ScreenProps) {
<Header
title="Événement"
left={<span onClick={() => navigate('events')} style={{ cursor: 'pointer' }}></span>}
right={isOwner && <span onClick={() => navigate('create-event')} style={{ cursor: 'pointer' }}></span>}
right={isOwner && <span onClick={() => navigate('update-event')} style={{ cursor: 'pointer' }}></span>}
/>
{/* Content */}
+1 -1
View File
@@ -40,7 +40,7 @@ export function ProfileScreen({ navigate }: ScreenProps) {
</div>
<div style={{ display: 'flex', gap: 8, marginTop: 20, justifyContent: 'center' }}>
<Button variant="primary">Modifier le profil</Button>
<Button variant="primary" onClick={() => navigate('update-profile')}>Modifier le profil</Button>
<Button onClick={() => navigate('share-profile')}>Partager</Button>
</div>
</div>
+68
View File
@@ -0,0 +1,68 @@
import React from 'react';
import { Header, Text, Input, Button, Avatar } from '../components/sketchy';
import type { ScreenProps } from './index';
export function UpdateProfileScreen({ navigate }: ScreenProps) {
return (
<div style={{ display: 'flex', flexDirection: 'column', height: '100%' }}>
<Header
title="Modifier le profil"
left={<span onClick={() => navigate('profile')} style={{ cursor: 'pointer' }}></span>}
/>
{/* Content */}
<div style={{ flex: 1, padding: 16, overflow: 'auto' }}>
{/* Photo */}
<div style={{ textAlign: 'center', marginBottom: 24 }}>
<Avatar initials="MD" size="lg" />
<Button style={{ marginTop: 12 }}>
Changer la photo
</Button>
</div>
<div style={{ display: 'flex', flexDirection: 'column', gap: 16 }}>
<div>
<Text style={{ marginBottom: 6, fontSize: 14 }}>Prénom *</Text>
<Input defaultValue="Marie" />
</div>
<div>
<Text style={{ marginBottom: 6, fontSize: 14 }}>Nom *</Text>
<Input defaultValue="Dupont" />
</div>
<div>
<Text style={{ marginBottom: 6, fontSize: 14 }}>Pseudo</Text>
<Input defaultValue="@mariedupont" />
</div>
<div>
<Text style={{ marginBottom: 6, fontSize: 14 }}>Localisation</Text>
<Input defaultValue="Lyon, France" placeholder="Ville, Pays" />
</div>
<div>
<Text style={{ marginBottom: 6, fontSize: 14 }}>Bio</Text>
<textarea
className="sketchy-input"
defaultValue="Passionnée de transition écologique et de rencontres humaines."
rows={3}
style={{ resize: 'none' }}
/>
</div>
</div>
</div>
{/* Footer */}
<div style={{ padding: 16, borderTop: '2px solid var(--sketch-black)' }}>
<Button
variant="primary"
style={{ width: '100%' }}
onClick={() => navigate('profile')}
>
Enregistrer
</Button>
</div>
</div>
);
}
+2
View File
@@ -13,6 +13,7 @@ import { ParticipantsListScreen } from './ParticipantsListScreen';
import { MeetingPointsScreen } from './MeetingPointsScreen';
import { FriendsListScreen } from './FriendsListScreen';
import { ShareProfileScreen } from './ShareProfileScreen';
import { UpdateProfileScreen } from './UpdateProfileScreen';
import { WelcomeScreen } from './WelcomeScreen';
export interface Screen {
@@ -58,6 +59,7 @@ export const screenGroups: ScreenGroup[] = [
name: 'Utilisateur',
screens: [
{ id: 'profile', name: 'Mon profil', component: ProfileScreen },
{ id: 'update-profile', name: 'Modifier mon profil', component: UpdateProfileScreen },
{ id: 'user-profile', name: 'Profil d\'un utilisateur', component: UserProfileScreen },
{ id: 'friends-list', name: 'Mon réseau', component: FriendsListScreen },
{ id: 'share-profile', name: 'Partager mon profil', component: ShareProfileScreen },