Suggest on creation + distance in kms

This commit is contained in:
Sylvain Duchesne
2026-01-26 18:32:16 +01:00
parent b7f86b139f
commit c9bc957d2a
14 changed files with 1236 additions and 657 deletions
+108 -4
View File
@@ -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 }}>
+1
View File
@@ -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>
+8 -1
View File
@@ -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')}
/>
+8 -2
View File
@@ -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')}
/>
+14 -6
View File
@@ -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>