Spaces:
Running
continue this project, a give a modern design
Browse filesconst MissionAventure = () => {
const [currentPage, setCurrentPage] = useState('home');
const [selectedMission, setSelectedMission] = useState(null);
const [searchTerm, setSearchTerm] = useState('');
const [selectedPassions, setSelectedPassions] = useState(['all']);
const [favorites, setFavorites] = useState([]);
const [formData, setFormData] = useState({ name: '', email: '', message: '' });
const [showApplicationForm, setShowApplicationForm] = useState(false);
const passions = [
{ id: 'all', label: 'Toutes', emoji: '✨' },
{ id: 'sustainability', label: 'Durabilité', emoji: '🌱' },
{ id: 'innovation', label: 'Innovation', emoji: '🚀' },
{ id: 'creativity', label: 'Créativité', emoji: '🎨' },
{ id: 'education', label: 'Éducation', emoji: '📚' },
{ id: 'technology', label: 'Technologie', emoji: '💻' },
{ id: 'social-impact', label: 'Impact Social', emoji: '🌍' }
];
const missions = [
{
id: 1,
title: 'Co-créer un atlas visuel de la mode durable parisienne',
client: 'Atelier Vert',
avatar: 'AV',
impact: 8.5,
emoji: '🌱',
passions: ['sustainability', 'creativity'],
tags: ['Durabilité', 'Storytelling', 'Photographie'],
duration: '3-4 semaines',
level: 'Défi modéré',
description: 'Réinventons ensemble comment la mode durable peut transformer l\'industrie parisienne. Cette mission vous invite à créer un atlas visuel qui celebrate les artisans et créateurs qui redéfinissent la mode.',
fullDescription: 'Rejoignez Atelier Vert pour un projet ambitieux et créatif. Nous cherchons un freelancer passionné par la mode durable pour documenter et raconter les histoires inspirantes des créateurs parisiens. Vous allez créer un atlas visuel complet qui servira de référence pour l\'industrie.',
requirements: ['Expérience en photographie', 'Sens du storytelling', 'Connaissance de la mode durable'],
budget: '€3,500 - €5,500',
location: 'Paris'
},
{
id: 2,
title: 'Développer une app de connexion intergénérationnelle',
client: 'TechPourTous',
avatar: 'TP',
impact: 9.2,
emoji: '🎯',
passions: ['innovation', 'technology'],
tags: ['Innovation', 'UX Design', 'Impact Social'],
duration: '6-8 semaines',
level: 'Grand défi',
description: 'Créons un pont numérique entre les générations ! Cette mission consiste à développer une application qui connecte les seniors avec les jeunes pour un apprentissage mutuel.',
fullDescription: 'TechPourTous cherche un développeur full-stack pour créer une plateforme innovante qui réunit les générations. L\'objectif est de faciliter l\'apprentissage mutuel et la transmission de savoirs entre seniors et jeunes adultes.',
requirements: ['Développement React/Vue', 'Design UX/UI', 'Base de données'],
budget: '€8,000 - €12,000',
location: 'Télétravail'
},
{
id: 3,
title: 'Co-concevoir un espace d\'apprentissage collaboratif',
client: 'LeMans Innovation',
avatar: 'LM',
impact: 7.8,
emoji: '📚',
passions: ['education', 'social-impact'],
tags: ['Éducation', 'Architecture', 'Innovation'],
duration: '4-5 semaines',
level: 'Défi créatif',
description: 'Transformons un espace physique en un laboratoire d\'apprentissage collaboratif pour les entrepreneurs locaux.',
fullDescription: 'LeMans Innovation souhaite réinventer un espace pour en faire un véritable lieu d\'innovation pédagogique. Nous recherchons un designer/architecte pour concevoir cet espace unique.',
requirements: ['Design d\'espace', 'Pédagogie innovante', 'Gestion de projet'],
budget: '€4,000 - €7,000',
location: 'Le Mans'
},
{
id: 4,
title: 'Créer une expérience sensorielle autour des bières artisanales',
client: 'Brasserie Paysanne',
avatar: 'BP',
impact: 8.1,
emoji: '🍺',
passions: ['creativity', 'innovation'],
tags: ['Créativité', 'Expérience', 'Storytelling'],
duration: '2-3 semaines',
level: 'Aventure rapide',
description: 'Développons une expérience immersive qui raconte l\'histoire de chaque bière artisanale à travers les sens.',
fullDescription: 'Brasserie Paysanne cherche un créateur d\'expériences pour concevoir une installation immersive unique. Votre mission sera de traduire la passion brassicole en une expérience mémorable.',
requirements: ['Design créatif', 'Storytelling', 'Connaissances en brasserie'],
budget: '€2,500 - €4,500',
location: 'Bretagne'
},
{
id: 5,
title: 'Concevoir une plateforme de démocratie participative locale',
client: 'Citoyen Connecté',
avatar: 'CC',
impact: 9.5,
emoji: '🌍',
passions: ['technology', 'social-impact'],
tags: ['Technologie', 'Démocratie', 'Innovation'],
duration: '8-10 semaines',
level: 'Mission majeure',
description: 'Bâtissons ensemble un outil numérique qui redynamise la participation citoyenne dans les villes moyennes.',
fullDescription: 'Citoyen Connecté lance un projet ambitieux pour transformer la démocratie locale. Nous recherchons une équipe multidisciplinaire pour concevoir une plateforme révolutionnaire.',
requirements: ['Développement web avancé', 'Architecture logicielle', 'Engagement civique'],
budget: '€12,000 - €18,000',
location: 'Télétravail'
},
{
id: 6,
title: 'Développer un curriculum d\'éducation alimentaire durable',
client: 'VertGouter',
avatar: 'VG',
impact: 8.8,
emoji: '🥕',
passions: ['sustainability', 'education'],
tags: ['Éducation', 'Durabilité', 'Pédagogie'],
duration: '5-6 semaines',
level: 'Défi éducatif',
description: 'Créons ensemble un programme éducatif qui transforme la relation des enfants à l\'alimentation.',
fullDescription: 'VertGouter souhaite créer un curriculum innovant pour enseigner l\'alimentation durable aux enfants. Nous cherchons un pédagogue passionné pour développer ce projet.',
requirements: ['Expertise en pédagogie', 'Connaissances en durabilité', 'Créativité'],
budget: '€3,500 - €6,000',
location: 'France'
}
];
const filteredMissions = missions.filter(mission => {
const matchesSearch = mission.title.toLowerCase().includes(searchTerm.toLowerCase()) ||
mission.client.toLowerCase().includes(searchTerm.toLowerCase());
const matchesPassion = selectedPassions.includes('all') ||
mission.passions.some(p => selectedPassions.includes(p));
return matchesSearch && matchesPassion;
});
const togglePassion = (passionId) => {
if (passionId === 'all') {
setSelectedPassions(['all']);
} else {
setSelectedPassions(prev => {
const updated = prev.filter(p => p !== 'all');
if (updated.includes(passionId)) {
return updated.filter(p => p !== passionId);
}
return [...updated, passionId];
});
}
};
const toggleFavorite = (missionId) => {
setFavorites(prev =>
prev.includes(missionId)
? prev.filter(id => id !== missionId)
: [...prev, missionId]
);
};
const handleFormChange = (e) => {
const { name, value } = e.target;
setFormData(prev => ({ ...prev, [name]: value }));
};
const handleFormSubmit = (e) => {
e.preventDefault();
console.log('Application submitted:', { ...formData, mission: selectedMission.id });
setFormData({ name: '', email: '', message: '' });
setShowApplicationForm(false);
alert('Candidature envoyée avec succès !');
};
return (
<div className="min-h-screen bg-gradient-to-br from-slate-50 to-slate-100">
{/* Header */}
<header className="sticky top-0 z-50 bg-white/95 backdrop-blur-lg border-b border-slate-200">
<div className="max-w-7xl mx-auto px-4 py-4 flex items-center justify-between">
<div className="flex items-center gap-2">
<div className="text-3xl">🚀</div>
<h1 className="text-2xl font-bold text-slate-900">MissionAventure</h1>
</div>
<div className="hidden md:flex items-center gap-8">
<button onClick={() => { setCurrentPage('home'); setSelectedMission(null); }} className="text-slate-700 hover:text-slate-900 transition">Missions</button>
<button onClick={() => setCurrentPage('home')} className="text-slate-700 hover:text-slate-900 transition">Comment ça marche</button>
<button onClick={() => setCurrentPage('home')} className="px-6 py-2 bg-gradient-to-r from-purple-600 to-pink-600 text-white rounded-lg hover:shadow-lg transition">Commencer</button>
</div>
</div>
</header>
{/* Mission Detail Page */}
{currentPage === 'mission-detail' && selectedMission && (
<main className="max-w-4xl mx-auto px-4 py-12">
<button onClick={() => { setCurrentPage('home'); setShowApplicationForm(false); }} className="flex items-center gap-2 text-purple-600 hover:text-purple-700 mb-8 transition">
<X size={20} /> Retour
</button>
<div className="bg-white rounded-2xl shadow-xl overflow-hidden">
<div className="h-48 bg-gradient-to-r from-purple-500 to-pink-500 flex items-center justify-center">
<div className="text-8xl">{selectedMission.emoji}</div>
</div>
<div className="p-8">
<div className="flex items-start justify-between mb-6">
<div>
<h1 className="text-4xl font-bold text-slate-900 mb-4">{selectedMission.title}</h1>
<div className="flex items-center gap-4 mb-6">
<div className="flex items-center gap-2">
<div className="w-12 h-12 rounded-full bg-gradient-to-br from-purple-400 to-pink-400 flex items-center justify-center text-white
- README.md +8 -5
- components/mission-card.js +225 -0
- components/navbar.js +100 -0
- index.html +499 -19
|
@@ -1,10 +1,13 @@
|
|
| 1 |
---
|
| 2 |
-
title:
|
| 3 |
-
|
| 4 |
-
|
| 5 |
-
|
| 6 |
sdk: static
|
| 7 |
pinned: false
|
|
|
|
|
|
|
| 8 |
---
|
| 9 |
|
| 10 |
-
|
|
|
|
|
|
| 1 |
---
|
| 2 |
+
title: MissionQuest 🚀✨
|
| 3 |
+
colorFrom: yellow
|
| 4 |
+
colorTo: purple
|
| 5 |
+
emoji: 🐳
|
| 6 |
sdk: static
|
| 7 |
pinned: false
|
| 8 |
+
tags:
|
| 9 |
+
- deepsite-v3
|
| 10 |
---
|
| 11 |
|
| 12 |
+
# Welcome to your new DeepSite project!
|
| 13 |
+
This project was created with [DeepSite](https://huggingface.co/deepsite).
|
|
@@ -0,0 +1,225 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
class MissionCard extends HTMLElement {
|
| 2 |
+
connectedCallback() {
|
| 3 |
+
this.attachShadow({ mode: 'open' });
|
| 4 |
+
this.shadowRoot.innerHTML = `
|
| 5 |
+
<style>
|
| 6 |
+
:host {
|
| 7 |
+
display: block;
|
| 8 |
+
background: white;
|
| 9 |
+
border-radius: 1rem;
|
| 10 |
+
overflow: hidden;
|
| 11 |
+
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
|
| 12 |
+
transition: all 0.3s ease;
|
| 13 |
+
}
|
| 14 |
+
|
| 15 |
+
:host(:hover) {
|
| 16 |
+
transform: translateY(-5px);
|
| 17 |
+
box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1);
|
| 18 |
+
}
|
| 19 |
+
|
| 20 |
+
.header {
|
| 21 |
+
height: 8rem;
|
| 22 |
+
background: linear-gradient(45deg, #6d28d9, #ec4899);
|
| 23 |
+
display: flex;
|
| 24 |
+
align-items: center;
|
| 25 |
+
justify-content: center;
|
| 26 |
+
position: relative;
|
| 27 |
+
}
|
| 28 |
+
|
| 29 |
+
.emoji {
|
| 30 |
+
font-size: 3rem;
|
| 31 |
+
}
|
| 32 |
+
|
| 33 |
+
.favorite-btn {
|
| 34 |
+
position: absolute;
|
| 35 |
+
top: 0.75rem;
|
| 36 |
+
right: 0.75rem;
|
| 37 |
+
background: rgba(255, 255, 255, 0.2);
|
| 38 |
+
border-radius: 50%;
|
| 39 |
+
width: 2.5rem;
|
| 40 |
+
height: 2.5rem;
|
| 41 |
+
display: flex;
|
| 42 |
+
align-items: center;
|
| 43 |
+
justify-content: center;
|
| 44 |
+
border: none;
|
| 45 |
+
cursor: pointer;
|
| 46 |
+
transition: all 0.2s;
|
| 47 |
+
}
|
| 48 |
+
|
| 49 |
+
.favorite-btn:hover {
|
| 50 |
+
background: rgba(255, 255, 255, 0.3);
|
| 51 |
+
}
|
| 52 |
+
|
| 53 |
+
.content {
|
| 54 |
+
padding: 1.5rem;
|
| 55 |
+
}
|
| 56 |
+
|
| 57 |
+
.client {
|
| 58 |
+
display: flex;
|
| 59 |
+
align-items: center;
|
| 60 |
+
gap: 0.75rem;
|
| 61 |
+
margin-bottom: 1rem;
|
| 62 |
+
}
|
| 63 |
+
|
| 64 |
+
.avatar {
|
| 65 |
+
width: 2.5rem;
|
| 66 |
+
height: 2.5rem;
|
| 67 |
+
border-radius: 50%;
|
| 68 |
+
background: linear-gradient(45deg, #6d28d9, #ec4899);
|
| 69 |
+
display: flex;
|
| 70 |
+
align-items: center;
|
| 71 |
+
justify-content: center;
|
| 72 |
+
color: white;
|
| 73 |
+
font-weight: bold;
|
| 74 |
+
font-size: 0.875rem;
|
| 75 |
+
}
|
| 76 |
+
|
| 77 |
+
.client-name {
|
| 78 |
+
font-size: 0.875rem;
|
| 79 |
+
color: #64748b;
|
| 80 |
+
font-weight: 600;
|
| 81 |
+
}
|
| 82 |
+
|
| 83 |
+
.title {
|
| 84 |
+
font-size: 1.125rem;
|
| 85 |
+
font-weight: 700;
|
| 86 |
+
color: #1e293b;
|
| 87 |
+
margin-bottom: 0.75rem;
|
| 88 |
+
display: -webkit-box;
|
| 89 |
+
-webkit-line-clamp: 2;
|
| 90 |
+
-webkit-box-orient: vertical;
|
| 91 |
+
overflow: hidden;
|
| 92 |
+
}
|
| 93 |
+
|
| 94 |
+
.description {
|
| 95 |
+
font-size: 0.875rem;
|
| 96 |
+
color: #64748b;
|
| 97 |
+
margin-bottom: 1rem;
|
| 98 |
+
display: -webkit-box;
|
| 99 |
+
-webkit-line-clamp: 2;
|
| 100 |
+
-webkit-box-orient: vertical;
|
| 101 |
+
overflow: hidden;
|
| 102 |
+
}
|
| 103 |
+
|
| 104 |
+
.stats {
|
| 105 |
+
display: flex;
|
| 106 |
+
align-items: center;
|
| 107 |
+
justify-content: space-between;
|
| 108 |
+
padding: 0.75rem 0;
|
| 109 |
+
border-top: 1px solid #e2e8f0;
|
| 110 |
+
border-bottom: 1px solid #e2e8f0;
|
| 111 |
+
margin-bottom: 1rem;
|
| 112 |
+
}
|
| 113 |
+
|
| 114 |
+
.stat {
|
| 115 |
+
display: flex;
|
| 116 |
+
align-items: center;
|
| 117 |
+
gap: 0.25rem;
|
| 118 |
+
}
|
| 119 |
+
|
| 120 |
+
.impact {
|
| 121 |
+
color: #f59e0b;
|
| 122 |
+
}
|
| 123 |
+
|
| 124 |
+
.duration {
|
| 125 |
+
color: #64748b;
|
| 126 |
+
}
|
| 127 |
+
|
| 128 |
+
.tags {
|
| 129 |
+
display: flex;
|
| 130 |
+
gap: 0.5rem;
|
| 131 |
+
flex-wrap: wrap;
|
| 132 |
+
margin-bottom: 1.5rem;
|
| 133 |
+
}
|
| 134 |
+
|
| 135 |
+
.tag {
|
| 136 |
+
font-size: 0.75rem;
|
| 137 |
+
padding: 0.25rem 0.75rem;
|
| 138 |
+
background: #f3e8ff;
|
| 139 |
+
color: #6d28d9;
|
| 140 |
+
border-radius: 9999px;
|
| 141 |
+
font-weight: 600;
|
| 142 |
+
}
|
| 143 |
+
|
| 144 |
+
.view-btn {
|
| 145 |
+
width: 100%;
|
| 146 |
+
padding: 0.75rem;
|
| 147 |
+
border-radius: 0.5rem;
|
| 148 |
+
background: linear-gradient(45deg, #6d28d9, #ec4899);
|
| 149 |
+
color: white;
|
| 150 |
+
font-weight: 600;
|
| 151 |
+
border: none;
|
| 152 |
+
cursor: pointer;
|
| 153 |
+
transition: all 0.2s;
|
| 154 |
+
display: flex;
|
| 155 |
+
align-items: center;
|
| 156 |
+
justify-content: center;
|
| 157 |
+
gap: 0.5rem;
|
| 158 |
+
}
|
| 159 |
+
|
| 160 |
+
.view-btn:hover {
|
| 161 |
+
transform: translateY(-2px);
|
| 162 |
+
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1);
|
| 163 |
+
}
|
| 164 |
+
|
| 165 |
+
.arrow {
|
| 166 |
+
transition: transform 0.2s;
|
| 167 |
+
}
|
| 168 |
+
|
| 169 |
+
:host(:hover) .arrow {
|
| 170 |
+
transform: translateX(2px);
|
| 171 |
+
}
|
| 172 |
+
</style>
|
| 173 |
+
|
| 174 |
+
<div class="header">
|
| 175 |
+
<div class="emoji">🚀</div>
|
| 176 |
+
<button class="favorite-btn">
|
| 177 |
+
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="white">
|
| 178 |
+
<path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z"></path>
|
| 179 |
+
</svg>
|
| 180 |
+
</button>
|
| 181 |
+
</div>
|
| 182 |
+
|
| 183 |
+
<div class="content">
|
| 184 |
+
<div class="client">
|
| 185 |
+
<div class="avatar">AV</div>
|
| 186 |
+
<span class="client-name">Atelier Vert</span>
|
| 187 |
+
</div>
|
| 188 |
+
|
| 189 |
+
<h3 class="title">Co-créer un atlas visuel de la mode durable parisienne</h3>
|
| 190 |
+
<p class="description">Réinventons ensemble comment la mode durable peut transformer l'industrie parisienne.</p>
|
| 191 |
+
|
| 192 |
+
<div class="stats">
|
| 193 |
+
<div class="stat">
|
| 194 |
+
<svg class="impact" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor">
|
| 195 |
+
<polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2"></polygon>
|
| 196 |
+
</svg>
|
| 197 |
+
<span>8.5/10</span>
|
| 198 |
+
</div>
|
| 199 |
+
<div class="stat">
|
| 200 |
+
<svg class="duration" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor">
|
| 201 |
+
<circle cx="12" cy="12" r="10"></circle>
|
| 202 |
+
<polyline points="12 6 12 12 16 14"></polyline>
|
| 203 |
+
</svg>
|
| 204 |
+
<span>3-4 semaines</span>
|
| 205 |
+
</div>
|
| 206 |
+
</div>
|
| 207 |
+
|
| 208 |
+
<div class="tags">
|
| 209 |
+
<span class="tag">Durabilité</span>
|
| 210 |
+
<span class="tag">Storytelling</span>
|
| 211 |
+
</div>
|
| 212 |
+
|
| 213 |
+
<button class="view-btn">
|
| 214 |
+
Voir les détails
|
| 215 |
+
<svg class="arrow" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor">
|
| 216 |
+
<path d="M5 12h14"></path>
|
| 217 |
+
<path d="M12 5l7 7-7 7"></path>
|
| 218 |
+
</svg>
|
| 219 |
+
</button>
|
| 220 |
+
</div>
|
| 221 |
+
`;
|
| 222 |
+
}
|
| 223 |
+
}
|
| 224 |
+
|
| 225 |
+
customElements.define('mission-card', MissionCard);
|
|
@@ -0,0 +1,100 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
class CustomNavbar extends HTMLElement {
|
| 2 |
+
connectedCallback() {
|
| 3 |
+
this.attachShadow({ mode: 'open' });
|
| 4 |
+
this.shadowRoot.innerHTML = `
|
| 5 |
+
<style>
|
| 6 |
+
:host {
|
| 7 |
+
display: block;
|
| 8 |
+
position: sticky;
|
| 9 |
+
top: 0;
|
| 10 |
+
z-index: 50;
|
| 11 |
+
background: rgba(255, 255, 255, 0.95);
|
| 12 |
+
backdrop-filter: blur(12px);
|
| 13 |
+
border-bottom: 1px solid rgba(0, 0, 0, 0.05);
|
| 14 |
+
}
|
| 15 |
+
|
| 16 |
+
nav {
|
| 17 |
+
max-width: 1280px;
|
| 18 |
+
margin: 0 auto;
|
| 19 |
+
padding: 1rem;
|
| 20 |
+
display: flex;
|
| 21 |
+
align-items: center;
|
| 22 |
+
justify-content: space-between;
|
| 23 |
+
}
|
| 24 |
+
|
| 25 |
+
.logo {
|
| 26 |
+
display: flex;
|
| 27 |
+
align-items: center;
|
| 28 |
+
gap: 0.75rem;
|
| 29 |
+
text-decoration: none;
|
| 30 |
+
}
|
| 31 |
+
|
| 32 |
+
.logo-icon {
|
| 33 |
+
font-size: 1.75rem;
|
| 34 |
+
}
|
| 35 |
+
|
| 36 |
+
.logo-text {
|
| 37 |
+
font-size: 1.25rem;
|
| 38 |
+
font-weight: 700;
|
| 39 |
+
color: #1e293b;
|
| 40 |
+
background: linear-gradient(45deg, #6d28d9, #ec4899);
|
| 41 |
+
-webkit-background-clip: text;
|
| 42 |
+
background-clip: text;
|
| 43 |
+
-webkit-text-fill-color: transparent;
|
| 44 |
+
}
|
| 45 |
+
|
| 46 |
+
.nav-links {
|
| 47 |
+
display: none;
|
| 48 |
+
gap: 2rem;
|
| 49 |
+
align-items: center;
|
| 50 |
+
}
|
| 51 |
+
|
| 52 |
+
.nav-link {
|
| 53 |
+
color: #64748b;
|
| 54 |
+
font-weight: 500;
|
| 55 |
+
text-decoration: none;
|
| 56 |
+
transition: color 0.2s;
|
| 57 |
+
}
|
| 58 |
+
|
| 59 |
+
.nav-link:hover {
|
| 60 |
+
color: #6d28d9;
|
| 61 |
+
}
|
| 62 |
+
|
| 63 |
+
.cta-btn {
|
| 64 |
+
padding: 0.5rem 1.5rem;
|
| 65 |
+
border-radius: 0.5rem;
|
| 66 |
+
font-weight: 600;
|
| 67 |
+
background: linear-gradient(45deg, #6d28d9, #ec4899);
|
| 68 |
+
color: white;
|
| 69 |
+
transition: all 0.2s;
|
| 70 |
+
}
|
| 71 |
+
|
| 72 |
+
.cta-btn:hover {
|
| 73 |
+
transform: translateY(-2px);
|
| 74 |
+
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1);
|
| 75 |
+
}
|
| 76 |
+
|
| 77 |
+
@media (min-width: 768px) {
|
| 78 |
+
.nav-links {
|
| 79 |
+
display: flex;
|
| 80 |
+
}
|
| 81 |
+
}
|
| 82 |
+
</style>
|
| 83 |
+
|
| 84 |
+
<nav>
|
| 85 |
+
<a href="/" class="logo">
|
| 86 |
+
<span class="logo-icon">🚀</span>
|
| 87 |
+
<span class="logo-text">MissionQuest</span>
|
| 88 |
+
</a>
|
| 89 |
+
|
| 90 |
+
<div class="nav-links">
|
| 91 |
+
<a href="#missions" class="nav-link">Missions</a>
|
| 92 |
+
<a href="#how-it-works" class="nav-link">Comment ça marche</a>
|
| 93 |
+
<a href="#get-started" class="cta-btn">Commencer</a>
|
| 94 |
+
</div>
|
| 95 |
+
</nav>
|
| 96 |
+
`;
|
| 97 |
+
}
|
| 98 |
+
}
|
| 99 |
+
|
| 100 |
+
customElements.define('custom-navbar', CustomNavbar);
|
|
@@ -1,19 +1,499 @@
|
|
| 1 |
-
|
| 2 |
-
|
| 3 |
-
|
| 4 |
-
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
|
| 18 |
-
|
| 19 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import React, { useState } from 'react';
|
| 2 |
+
import { Search, Filter, X, Heart, MapPin, Clock, Zap, ChevronRight } from 'lucide-react';
|
| 3 |
+
|
| 4 |
+
const MissionAventure = () => {
|
| 5 |
+
const [currentPage, setCurrentPage] = useState('home');
|
| 6 |
+
const [selectedMission, setSelectedMission] = useState(null);
|
| 7 |
+
const [searchTerm, setSearchTerm] = useState('');
|
| 8 |
+
const [selectedPassions, setSelectedPassions] = useState(['all']);
|
| 9 |
+
const [favorites, setFavorites] = useState([]);
|
| 10 |
+
const [formData, setFormData] = useState({ name: '', email: '', message: '' });
|
| 11 |
+
const [showApplicationForm, setShowApplicationForm] = useState(false);
|
| 12 |
+
|
| 13 |
+
const passions = [
|
| 14 |
+
{ id: 'all', label: 'Toutes', emoji: '✨' },
|
| 15 |
+
{ id: 'sustainability', label: 'Durabilité', emoji: '🌱' },
|
| 16 |
+
{ id: 'innovation', label: 'Innovation', emoji: '🚀' },
|
| 17 |
+
{ id: 'creativity', label: 'Créativité', emoji: '🎨' },
|
| 18 |
+
{ id: 'education', label: 'Éducation', emoji: '📚' },
|
| 19 |
+
{ id: 'technology', label: 'Technologie', emoji: '💻' },
|
| 20 |
+
{ id: 'social-impact', label: 'Impact Social', emoji: '🌍' }
|
| 21 |
+
];
|
| 22 |
+
|
| 23 |
+
const missions = [
|
| 24 |
+
{
|
| 25 |
+
id: 1,
|
| 26 |
+
title: 'Co-créer un atlas visuel de la mode durable parisienne',
|
| 27 |
+
client: 'Atelier Vert',
|
| 28 |
+
avatar: 'AV',
|
| 29 |
+
impact: 8.5,
|
| 30 |
+
emoji: '🌱',
|
| 31 |
+
passions: ['sustainability', 'creativity'],
|
| 32 |
+
tags: ['Durabilité', 'Storytelling', 'Photographie'],
|
| 33 |
+
duration: '3-4 semaines',
|
| 34 |
+
level: 'Défi modéré',
|
| 35 |
+
description: 'Réinventons ensemble comment la mode durable peut transformer l\'industrie parisienne. Cette mission vous invite à créer un atlas visuel qui celebrate les artisans et créateurs qui redéfinissent la mode.',
|
| 36 |
+
fullDescription: 'Rejoignez Atelier Vert pour un projet ambitieux et créatif. Nous cherchons un freelancer passionné par la mode durable pour documenter et raconter les histoires inspirantes des créateurs parisiens. Vous allez créer un atlas visuel complet qui servira de référence pour l\'industrie.',
|
| 37 |
+
requirements: ['Expérience en photographie', 'Sens du storytelling', 'Connaissance de la mode durable'],
|
| 38 |
+
budget: '€3,500 - €5,500',
|
| 39 |
+
location: 'Paris'
|
| 40 |
+
},
|
| 41 |
+
{
|
| 42 |
+
id: 2,
|
| 43 |
+
title: 'Développer une app de connexion intergénérationnelle',
|
| 44 |
+
client: 'TechPourTous',
|
| 45 |
+
avatar: 'TP',
|
| 46 |
+
impact: 9.2,
|
| 47 |
+
emoji: '🎯',
|
| 48 |
+
passions: ['innovation', 'technology'],
|
| 49 |
+
tags: ['Innovation', 'UX Design', 'Impact Social'],
|
| 50 |
+
duration: '6-8 semaines',
|
| 51 |
+
level: 'Grand défi',
|
| 52 |
+
description: 'Créons un pont numérique entre les générations ! Cette mission consiste à développer une application qui connecte les seniors avec les jeunes pour un apprentissage mutuel.',
|
| 53 |
+
fullDescription: 'TechPourTous cherche un développeur full-stack pour créer une plateforme innovante qui réunit les générations. L\'objectif est de faciliter l\'apprentissage mutuel et la transmission de savoirs entre seniors et jeunes adultes.',
|
| 54 |
+
requirements: ['Développement React/Vue', 'Design UX/UI', 'Base de données'],
|
| 55 |
+
budget: '€8,000 - €12,000',
|
| 56 |
+
location: 'Télétravail'
|
| 57 |
+
},
|
| 58 |
+
{
|
| 59 |
+
id: 3,
|
| 60 |
+
title: 'Co-concevoir un espace d\'apprentissage collaboratif',
|
| 61 |
+
client: 'LeMans Innovation',
|
| 62 |
+
avatar: 'LM',
|
| 63 |
+
impact: 7.8,
|
| 64 |
+
emoji: '📚',
|
| 65 |
+
passions: ['education', 'social-impact'],
|
| 66 |
+
tags: ['Éducation', 'Architecture', 'Innovation'],
|
| 67 |
+
duration: '4-5 semaines',
|
| 68 |
+
level: 'Défi créatif',
|
| 69 |
+
description: 'Transformons un espace physique en un laboratoire d\'apprentissage collaboratif pour les entrepreneurs locaux.',
|
| 70 |
+
fullDescription: 'LeMans Innovation souhaite réinventer un espace pour en faire un véritable lieu d\'innovation pédagogique. Nous recherchons un designer/architecte pour concevoir cet espace unique.',
|
| 71 |
+
requirements: ['Design d\'espace', 'Pédagogie innovante', 'Gestion de projet'],
|
| 72 |
+
budget: '€4,000 - €7,000',
|
| 73 |
+
location: 'Le Mans'
|
| 74 |
+
},
|
| 75 |
+
{
|
| 76 |
+
id: 4,
|
| 77 |
+
title: 'Créer une expérience sensorielle autour des bières artisanales',
|
| 78 |
+
client: 'Brasserie Paysanne',
|
| 79 |
+
avatar: 'BP',
|
| 80 |
+
impact: 8.1,
|
| 81 |
+
emoji: '🍺',
|
| 82 |
+
passions: ['creativity', 'innovation'],
|
| 83 |
+
tags: ['Créativité', 'Expérience', 'Storytelling'],
|
| 84 |
+
duration: '2-3 semaines',
|
| 85 |
+
level: 'Aventure rapide',
|
| 86 |
+
description: 'Développons une expérience immersive qui raconte l\'histoire de chaque bière artisanale à travers les sens.',
|
| 87 |
+
fullDescription: 'Brasserie Paysanne cherche un créateur d\'expériences pour concevoir une installation immersive unique. Votre mission sera de traduire la passion brassicole en une expérience mémorable.',
|
| 88 |
+
requirements: ['Design créatif', 'Storytelling', 'Connaissances en brasserie'],
|
| 89 |
+
budget: '€2,500 - €4,500',
|
| 90 |
+
location: 'Bretagne'
|
| 91 |
+
},
|
| 92 |
+
{
|
| 93 |
+
id: 5,
|
| 94 |
+
title: 'Concevoir une plateforme de démocratie participative locale',
|
| 95 |
+
client: 'Citoyen Connecté',
|
| 96 |
+
avatar: 'CC',
|
| 97 |
+
impact: 9.5,
|
| 98 |
+
emoji: '🌍',
|
| 99 |
+
passions: ['technology', 'social-impact'],
|
| 100 |
+
tags: ['Technologie', 'Démocratie', 'Innovation'],
|
| 101 |
+
duration: '8-10 semaines',
|
| 102 |
+
level: 'Mission majeure',
|
| 103 |
+
description: 'Bâtissons ensemble un outil numérique qui redynamise la participation citoyenne dans les villes moyennes.',
|
| 104 |
+
fullDescription: 'Citoyen Connecté lance un projet ambitieux pour transformer la démocratie locale. Nous recherchons une équipe multidisciplinaire pour concevoir une plateforme révolutionnaire.',
|
| 105 |
+
requirements: ['Développement web avancé', 'Architecture logicielle', 'Engagement civique'],
|
| 106 |
+
budget: '€12,000 - €18,000',
|
| 107 |
+
location: 'Télétravail'
|
| 108 |
+
},
|
| 109 |
+
{
|
| 110 |
+
id: 6,
|
| 111 |
+
title: 'Développer un curriculum d\'éducation alimentaire durable',
|
| 112 |
+
client: 'VertGouter',
|
| 113 |
+
avatar: 'VG',
|
| 114 |
+
impact: 8.8,
|
| 115 |
+
emoji: '🥕',
|
| 116 |
+
passions: ['sustainability', 'education'],
|
| 117 |
+
tags: ['Éducation', 'Durabilité', 'Pédagogie'],
|
| 118 |
+
duration: '5-6 semaines',
|
| 119 |
+
level: 'Défi éducatif',
|
| 120 |
+
description: 'Créons ensemble un programme éducatif qui transforme la relation des enfants à l\'alimentation.',
|
| 121 |
+
fullDescription: 'VertGouter souhaite créer un curriculum innovant pour enseigner l\'alimentation durable aux enfants. Nous cherchons un pédagogue passionné pour développer ce projet.',
|
| 122 |
+
requirements: ['Expertise en pédagogie', 'Connaissances en durabilité', 'Créativité'],
|
| 123 |
+
budget: '€3,500 - €6,000',
|
| 124 |
+
location: 'France'
|
| 125 |
+
}
|
| 126 |
+
];
|
| 127 |
+
|
| 128 |
+
const filteredMissions = missions.filter(mission => {
|
| 129 |
+
const matchesSearch = mission.title.toLowerCase().includes(searchTerm.toLowerCase()) ||
|
| 130 |
+
mission.client.toLowerCase().includes(searchTerm.toLowerCase());
|
| 131 |
+
const matchesPassion = selectedPassions.includes('all') ||
|
| 132 |
+
mission.passions.some(p => selectedPassions.includes(p));
|
| 133 |
+
return matchesSearch && matchesPassion;
|
| 134 |
+
});
|
| 135 |
+
|
| 136 |
+
const togglePassion = (passionId) => {
|
| 137 |
+
if (passionId === 'all') {
|
| 138 |
+
setSelectedPassions(['all']);
|
| 139 |
+
} else {
|
| 140 |
+
setSelectedPassions(prev => {
|
| 141 |
+
const updated = prev.filter(p => p !== 'all');
|
| 142 |
+
if (updated.includes(passionId)) {
|
| 143 |
+
return updated.filter(p => p !== passionId);
|
| 144 |
+
}
|
| 145 |
+
return [...updated, passionId];
|
| 146 |
+
});
|
| 147 |
+
}
|
| 148 |
+
};
|
| 149 |
+
|
| 150 |
+
const toggleFavorite = (missionId) => {
|
| 151 |
+
setFavorites(prev =>
|
| 152 |
+
prev.includes(missionId)
|
| 153 |
+
? prev.filter(id => id !== missionId)
|
| 154 |
+
: [...prev, missionId]
|
| 155 |
+
);
|
| 156 |
+
};
|
| 157 |
+
|
| 158 |
+
const handleFormChange = (e) => {
|
| 159 |
+
const { name, value } = e.target;
|
| 160 |
+
setFormData(prev => ({ ...prev, [name]: value }));
|
| 161 |
+
};
|
| 162 |
+
|
| 163 |
+
const handleFormSubmit = (e) => {
|
| 164 |
+
e.preventDefault();
|
| 165 |
+
console.log('Application submitted:', { ...formData, mission: selectedMission.id });
|
| 166 |
+
setFormData({ name: '', email: '', message: '' });
|
| 167 |
+
setShowApplicationForm(false);
|
| 168 |
+
alert('Candidature envoyée avec succès !');
|
| 169 |
+
};
|
| 170 |
+
|
| 171 |
+
return (
|
| 172 |
+
<div className="min-h-screen bg-gradient-to-br from-slate-50 to-slate-100">
|
| 173 |
+
{/* Header */}
|
| 174 |
+
<header className="sticky top-0 z-50 bg-white/95 backdrop-blur-lg border-b border-slate-200">
|
| 175 |
+
<div className="max-w-7xl mx-auto px-4 py-4 flex items-center justify-between">
|
| 176 |
+
<div className="flex items-center gap-2">
|
| 177 |
+
<div className="text-3xl">🚀</div>
|
| 178 |
+
<h1 className="text-2xl font-bold text-slate-900">MissionAventure</h1>
|
| 179 |
+
</div>
|
| 180 |
+
<div className="hidden md:flex items-center gap-8">
|
| 181 |
+
<button onClick={() => { setCurrentPage('home'); setSelectedMission(null); }} className="text-slate-700 hover:text-slate-900 transition">Missions</button>
|
| 182 |
+
<button onClick={() => setCurrentPage('home')} className="text-slate-700 hover:text-slate-900 transition">Comment ça marche</button>
|
| 183 |
+
<button onClick={() => setCurrentPage('home')} className="px-6 py-2 bg-gradient-to-r from-purple-600 to-pink-600 text-white rounded-lg hover:shadow-lg transition">Commencer</button>
|
| 184 |
+
</div>
|
| 185 |
+
</div>
|
| 186 |
+
</header>
|
| 187 |
+
|
| 188 |
+
{/* Mission Detail Page */}
|
| 189 |
+
{currentPage === 'mission-detail' && selectedMission && (
|
| 190 |
+
<main className="max-w-4xl mx-auto px-4 py-12">
|
| 191 |
+
<button onClick={() => { setCurrentPage('home'); setShowApplicationForm(false); }} className="flex items-center gap-2 text-purple-600 hover:text-purple-700 mb-8 transition">
|
| 192 |
+
<X size={20} /> Retour
|
| 193 |
+
</button>
|
| 194 |
+
|
| 195 |
+
<div className="bg-white rounded-2xl shadow-xl overflow-hidden">
|
| 196 |
+
<div className="h-48 bg-gradient-to-r from-purple-500 to-pink-500 flex items-center justify-center">
|
| 197 |
+
<div className="text-8xl">{selectedMission.emoji}</div>
|
| 198 |
+
</div>
|
| 199 |
+
|
| 200 |
+
<div className="p-8">
|
| 201 |
+
<div className="flex items-start justify-between mb-6">
|
| 202 |
+
<div>
|
| 203 |
+
<h1 className="text-4xl font-bold text-slate-900 mb-4">{selectedMission.title}</h1>
|
| 204 |
+
<div className="flex items-center gap-4 mb-6">
|
| 205 |
+
<div className="flex items-center gap-2">
|
| 206 |
+
<div className="w-12 h-12 rounded-full bg-gradient-to-br from-purple-400 to-pink-400 flex items-center justify-center text-white font-bold">
|
| 207 |
+
{selectedMission.avatar}
|
| 208 |
+
</div>
|
| 209 |
+
<span className="font-semibold text-slate-700">{selectedMission.client}</span>
|
| 210 |
+
</div>
|
| 211 |
+
</div>
|
| 212 |
+
</div>
|
| 213 |
+
<button
|
| 214 |
+
onClick={() => toggleFavorite(selectedMission.id)}
|
| 215 |
+
className="transition transform hover:scale-110"
|
| 216 |
+
>
|
| 217 |
+
<Heart
|
| 218 |
+
size={32}
|
| 219 |
+
fill={favorites.includes(selectedMission.id) ? '#ec4899' : 'none'}
|
| 220 |
+
stroke={favorites.includes(selectedMission.id) ? '#ec4899' : '#cbd5e1'}
|
| 221 |
+
/>
|
| 222 |
+
</button>
|
| 223 |
+
</div>
|
| 224 |
+
|
| 225 |
+
<div className="grid md:grid-cols-3 gap-4 mb-8">
|
| 226 |
+
<div className="bg-slate-50 p-4 rounded-lg">
|
| 227 |
+
<div className="flex items-center gap-2 text-slate-600 mb-2">
|
| 228 |
+
<Zap size={18} />
|
| 229 |
+
<span className="text-sm font-semibold">Impact</span>
|
| 230 |
+
</div>
|
| 231 |
+
<div className="text-3xl font-bold text-purple-600">{selectedMission.impact}/10</div>
|
| 232 |
+
</div>
|
| 233 |
+
<div className="bg-slate-50 p-4 rounded-lg">
|
| 234 |
+
<div className="flex items-center gap-2 text-slate-600 mb-2">
|
| 235 |
+
<Clock size={18} />
|
| 236 |
+
<span className="text-sm font-semibold">Durée</span>
|
| 237 |
+
</div>
|
| 238 |
+
<div className="text-lg font-semibold text-slate-900">{selectedMission.duration}</div>
|
| 239 |
+
</div>
|
| 240 |
+
<div className="bg-slate-50 p-4 rounded-lg">
|
| 241 |
+
<div className="flex items-center gap-2 text-slate-600 mb-2">
|
| 242 |
+
<MapPin size={18} />
|
| 243 |
+
<span className="text-sm font-semibold">Budget</span>
|
| 244 |
+
</div>
|
| 245 |
+
<div className="text-lg font-semibold text-slate-900">{selectedMission.budget}</div>
|
| 246 |
+
</div>
|
| 247 |
+
</div>
|
| 248 |
+
|
| 249 |
+
<div className="mb-8">
|
| 250 |
+
<h2 className="text-2xl font-bold text-slate-900 mb-4">À propos de la mission</h2>
|
| 251 |
+
<p className="text-lg text-slate-700 leading-relaxed mb-4">{selectedMission.fullDescription}</p>
|
| 252 |
+
</div>
|
| 253 |
+
|
| 254 |
+
<div className="mb-8">
|
| 255 |
+
<h3 className="text-xl font-bold text-slate-900 mb-4">Compétences requises</h3>
|
| 256 |
+
<ul className="space-y-2">
|
| 257 |
+
{selectedMission.requirements.map((req, i) => (
|
| 258 |
+
<li key={i} className="flex items-center gap-3 text-slate-700">
|
| 259 |
+
<div className="w-2 h-2 rounded-full bg-purple-600" />
|
| 260 |
+
{req}
|
| 261 |
+
</li>
|
| 262 |
+
))}
|
| 263 |
+
</ul>
|
| 264 |
+
</div>
|
| 265 |
+
|
| 266 |
+
<div className="mb-8">
|
| 267 |
+
<h3 className="text-xl font-bold text-slate-900 mb-4">Tags</h3>
|
| 268 |
+
<div className="flex flex-wrap gap-2">
|
| 269 |
+
{selectedMission.tags.map((tag, i) => (
|
| 270 |
+
<span key={i} className="px-4 py-2 bg-purple-100 text-purple-700 rounded-full text-sm font-semibold">
|
| 271 |
+
{tag}
|
| 272 |
+
</span>
|
| 273 |
+
))}
|
| 274 |
+
</div>
|
| 275 |
+
</div>
|
| 276 |
+
|
| 277 |
+
{showApplicationForm ? (
|
| 278 |
+
<div className="bg-gradient-to-br from-purple-50 to-pink-50 p-8 rounded-xl">
|
| 279 |
+
<h3 className="text-2xl font-bold text-slate-900 mb-6">Postuler à cette mission</h3>
|
| 280 |
+
<div className="space-y-4">
|
| 281 |
+
<div>
|
| 282 |
+
<label className="block text-sm font-semibold text-slate-700 mb-2">Nom complet</label>
|
| 283 |
+
<input
|
| 284 |
+
type="text"
|
| 285 |
+
name="name"
|
| 286 |
+
value={formData.name}
|
| 287 |
+
onChange={handleFormChange}
|
| 288 |
+
className="w-full px-4 py-3 border border-slate-300 rounded-lg focus:outline-none focus:border-purple-500 focus:ring-2 focus:ring-purple-200"
|
| 289 |
+
placeholder="Votre nom"
|
| 290 |
+
/>
|
| 291 |
+
</div>
|
| 292 |
+
<div>
|
| 293 |
+
<label className="block text-sm font-semibold text-slate-700 mb-2">Email</label>
|
| 294 |
+
<input
|
| 295 |
+
type="email"
|
| 296 |
+
name="email"
|
| 297 |
+
value={formData.email}
|
| 298 |
+
onChange={handleFormChange}
|
| 299 |
+
className="w-full px-4 py-3 border border-slate-300 rounded-lg focus:outline-none focus:border-purple-500 focus:ring-2 focus:ring-purple-200"
|
| 300 |
+
placeholder="[email protected]"
|
| 301 |
+
/>
|
| 302 |
+
</div>
|
| 303 |
+
<div>
|
| 304 |
+
<label className="block text-sm font-semibold text-slate-700 mb-2">Message de candidature</label>
|
| 305 |
+
<textarea
|
| 306 |
+
name="message"
|
| 307 |
+
value={formData.message}
|
| 308 |
+
onChange={handleFormChange}
|
| 309 |
+
rows="5"
|
| 310 |
+
className="w-full px-4 py-3 border border-slate-300 rounded-lg focus:outline-none focus:border-purple-500 focus:ring-2 focus:ring-purple-200"
|
| 311 |
+
placeholder="Dites-nous pourquoi vous êtes intéressé..."
|
| 312 |
+
/>
|
| 313 |
+
</div>
|
| 314 |
+
<div className="flex gap-4">
|
| 315 |
+
<button
|
| 316 |
+
onClick={handleFormSubmit}
|
| 317 |
+
className="flex-1 py-3 bg-gradient-to-r from-purple-600 to-pink-600 text-white font-bold rounded-lg hover:shadow-lg transition"
|
| 318 |
+
>
|
| 319 |
+
Envoyer ma candidature
|
| 320 |
+
</button>
|
| 321 |
+
<button
|
| 322 |
+
onClick={() => setShowApplicationForm(false)}
|
| 323 |
+
className="flex-1 py-3 border border-slate-300 text-slate-700 font-bold rounded-lg hover:bg-slate-50 transition"
|
| 324 |
+
>
|
| 325 |
+
Annuler
|
| 326 |
+
</button>
|
| 327 |
+
</div>
|
| 328 |
+
</div>
|
| 329 |
+
</div>
|
| 330 |
+
) : (
|
| 331 |
+
<button
|
| 332 |
+
onClick={() => setShowApplicationForm(true)}
|
| 333 |
+
className="w-full py-4 bg-gradient-to-r from-purple-600 to-pink-600 text-white font-bold text-lg rounded-lg hover:shadow-lg transition transform hover:scale-105"
|
| 334 |
+
>
|
| 335 |
+
Postuler à cette mission
|
| 336 |
+
</button>
|
| 337 |
+
)}
|
| 338 |
+
</div>
|
| 339 |
+
</div>
|
| 340 |
+
</main>
|
| 341 |
+
)}
|
| 342 |
+
|
| 343 |
+
{/* Home Page */}
|
| 344 |
+
{currentPage === 'home' && (
|
| 345 |
+
<>
|
| 346 |
+
{/* Hero Section */}
|
| 347 |
+
<section className="max-w-7xl mx-auto px-4 py-20">
|
| 348 |
+
<div className="grid md:grid-cols-2 gap-12 items-center">
|
| 349 |
+
<div>
|
| 350 |
+
<h2 className="text-5xl md:text-6xl font-bold text-slate-900 mb-6 leading-tight">
|
| 351 |
+
Votre prochaine mission est une <span className="bg-gradient-to-r from-purple-600 to-pink-600 bg-clip-text text-transparent">aventure</span>
|
| 352 |
+
</h2>
|
| 353 |
+
<p className="text-xl text-slate-600 mb-8">
|
| 354 |
+
Découvrez un travail significatif qui s'aligne avec vos passions et nourrit votre croissance
|
| 355 |
+
</p>
|
| 356 |
+
<button className="px-8 py-4 bg-gradient-to-r from-purple-600 to-pink-600 text-white font-bold rounded-lg hover:shadow-lg transition transform hover:scale-105">
|
| 357 |
+
Trouver une Mission
|
| 358 |
+
</button>
|
| 359 |
+
</div>
|
| 360 |
+
<div className="grid grid-cols-2 gap-4">
|
| 361 |
+
{['🎨', '🚀', '🌱', '💡'].map((emoji, i) => (
|
| 362 |
+
<div key={i} className="aspect-square bg-gradient-to-br from-purple-100 to-pink-100 rounded-2xl flex items-center justify-center text-6xl hover:scale-110 transition">
|
| 363 |
+
{emoji}
|
| 364 |
+
</div>
|
| 365 |
+
))}
|
| 366 |
+
</div>
|
| 367 |
+
</div>
|
| 368 |
+
</section>
|
| 369 |
+
|
| 370 |
+
{/* Search and Filters */}
|
| 371 |
+
<section className="max-w-7xl mx-auto px-4 py-12">
|
| 372 |
+
<div className="bg-white rounded-2xl shadow-lg p-8">
|
| 373 |
+
<div className="mb-8">
|
| 374 |
+
<div className="relative">
|
| 375 |
+
<Search className="absolute left-4 top-4 text-slate-400" size={24} />
|
| 376 |
+
<input
|
| 377 |
+
type="text"
|
| 378 |
+
placeholder="Rechercher une mission ou un client..."
|
| 379 |
+
value={searchTerm}
|
| 380 |
+
onChange={(e) => setSearchTerm(e.target.value)}
|
| 381 |
+
className="w-full pl-12 pr-4 py-3 border-2 border-slate-200 rounded-lg focus:outline-none focus:border-purple-500 text-lg"
|
| 382 |
+
/>
|
| 383 |
+
</div>
|
| 384 |
+
</div>
|
| 385 |
+
|
| 386 |
+
<div>
|
| 387 |
+
<h3 className="text-sm font-bold text-slate-600 uppercase tracking-wide mb-4 flex items-center gap-2">
|
| 388 |
+
<Filter size={18} />
|
| 389 |
+
Filtrer par passion
|
| 390 |
+
</h3>
|
| 391 |
+
<div className="flex flex-wrap gap-3">
|
| 392 |
+
{passions.map(passion => (
|
| 393 |
+
<button
|
| 394 |
+
key={passion.id}
|
| 395 |
+
onClick={() => togglePassion(passion.id)}
|
| 396 |
+
className={`px-4 py-2 rounded-full font-semibold transition ${
|
| 397 |
+
selectedPassions.includes(passion.id)
|
| 398 |
+
? 'bg-gradient-to-r from-purple-600 to-pink-600 text-white shadow-lg'
|
| 399 |
+
: 'bg-slate-100 text-slate-700 hover:bg-slate-200'
|
| 400 |
+
}`}
|
| 401 |
+
>
|
| 402 |
+
{passion.emoji} {passion.label}
|
| 403 |
+
</button>
|
| 404 |
+
))}
|
| 405 |
+
</div>
|
| 406 |
+
</div>
|
| 407 |
+
</div>
|
| 408 |
+
|
| 409 |
+
<p className="text-slate-600 mt-6 text-center">
|
| 410 |
+
{filteredMissions.length} mission{filteredMissions.length > 1 ? 's' : ''} trouvée{filteredMissions.length > 1 ? 's' : ''}
|
| 411 |
+
</p>
|
| 412 |
+
</section>
|
| 413 |
+
|
| 414 |
+
{/* Missions Grid */}
|
| 415 |
+
<section className="max-w-7xl mx-auto px-4 pb-20">
|
| 416 |
+
<div className="grid md:grid-cols-2 lg:grid-cols-3 gap-6">
|
| 417 |
+
{filteredMissions.map(mission => (
|
| 418 |
+
<div
|
| 419 |
+
key={mission.id}
|
| 420 |
+
className="group bg-white rounded-2xl shadow-lg overflow-hidden hover:shadow-2xl transition transform hover:scale-105"
|
| 421 |
+
>
|
| 422 |
+
<div className="h-32 bg-gradient-to-r from-purple-500 to-pink-500 flex items-center justify-center text-6xl relative">
|
| 423 |
+
{mission.emoji}
|
| 424 |
+
<button
|
| 425 |
+
onClick={() => toggleFavorite(mission.id)}
|
| 426 |
+
className="absolute top-3 right-3 transition"
|
| 427 |
+
>
|
| 428 |
+
<Heart
|
| 429 |
+
size={24}
|
| 430 |
+
fill={favorites.includes(mission.id) ? '#ffffff' : 'none'}
|
| 431 |
+
stroke="#ffffff"
|
| 432 |
+
/>
|
| 433 |
+
</button>
|
| 434 |
+
</div>
|
| 435 |
+
|
| 436 |
+
<div className="p-6">
|
| 437 |
+
<div className="flex items-center gap-3 mb-4">
|
| 438 |
+
<div className="w-10 h-10 rounded-full bg-gradient-to-br from-purple-400 to-pink-400 flex items-center justify-center text-white text-sm font-bold">
|
| 439 |
+
{mission.avatar}
|
| 440 |
+
</div>
|
| 441 |
+
<span className="font-semibold text-slate-700 text-sm">{mission.client}</span>
|
| 442 |
+
</div>
|
| 443 |
+
|
| 444 |
+
<h3 className="font-bold text-slate-900 mb-3 line-clamp-2 group-hover:text-purple-600 transition">
|
| 445 |
+
{mission.title}
|
| 446 |
+
</h3>
|
| 447 |
+
|
| 448 |
+
<p className="text-slate-600 text-sm mb-4 line-clamp-2">
|
| 449 |
+
{mission.description}
|
| 450 |
+
</p>
|
| 451 |
+
|
| 452 |
+
<div className="flex items-center justify-between mb-4 py-3 border-t border-b border-slate-100">
|
| 453 |
+
<div className="flex items-center gap-2">
|
| 454 |
+
<Zap size={16} className="text-amber-500" />
|
| 455 |
+
<span className="text-sm font-semibold text-slate-700">{mission.impact}/10</span>
|
| 456 |
+
</div>
|
| 457 |
+
<div className="flex items-center gap-2">
|
| 458 |
+
<Clock size={16} className="text-slate-500" />
|
| 459 |
+
<span className="text-sm font-semibold text-slate-700">{mission.duration}</span>
|
| 460 |
+
</div>
|
| 461 |
+
</div>
|
| 462 |
+
|
| 463 |
+
<div className="flex flex-wrap gap-2 mb-6">
|
| 464 |
+
{mission.tags.slice(0, 2).map((tag, i) => (
|
| 465 |
+
<span key={i} className="text-xs px-3 py-1 bg-purple-100 text-purple-700 rounded-full font-semibold">
|
| 466 |
+
{tag}
|
| 467 |
+
</span>
|
| 468 |
+
))}
|
| 469 |
+
</div>
|
| 470 |
+
|
| 471 |
+
<button
|
| 472 |
+
onClick={() => {
|
| 473 |
+
setSelectedMission(mission);
|
| 474 |
+
setCurrentPage('mission-detail');
|
| 475 |
+
}}
|
| 476 |
+
className="w-full py-3 bg-gradient-to-r from-purple-600 to-pink-600 text-white font-bold rounded-lg hover:shadow-lg transition flex items-center justify-center gap-2 group"
|
| 477 |
+
>
|
| 478 |
+
Voir les détails
|
| 479 |
+
<ChevronRight size={18} className="group-hover:translate-x-1 transition" />
|
| 480 |
+
</button>
|
| 481 |
+
</div>
|
| 482 |
+
</div>
|
| 483 |
+
))}
|
| 484 |
+
</div>
|
| 485 |
+
|
| 486 |
+
{filteredMissions.length === 0 && (
|
| 487 |
+
<div className="text-center py-20">
|
| 488 |
+
<div className="text-6xl mb-4">🔍</div>
|
| 489 |
+
<h3 className="text-2xl font-bold text-slate-900 mb-2">Aucune mission trouvée</h3>
|
| 490 |
+
<p className="text-slate-600">Essayez d'ajuster vos filtres ou votre recherche</p>
|
| 491 |
+
</div>
|
| 492 |
+
)}
|
| 493 |
+
</section>
|
| 494 |
+
</>
|
| 495 |
+
)}
|
| 496 |
+
</div>
|
| 497 |
+
);
|
| 498 |
+
};
|
| 499 |
+
<script src="https://huggingface.co/deepsite/deepsite-badge.js"></script>
|