diff --git a/artifacts/voix-du-peuple/src/App.tsx b/artifacts/voix-du-peuple/src/App.tsx index 66c9b49..9396c0d 100644 --- a/artifacts/voix-du-peuple/src/App.tsx +++ b/artifacts/voix-du-peuple/src/App.tsx @@ -23,8 +23,8 @@ function Navbar() { La Voix du Peuple diff --git a/artifacts/voix-du-peuple/src/pages/about.tsx b/artifacts/voix-du-peuple/src/pages/about.tsx index 6e5b8b7..defc094 100644 --- a/artifacts/voix-du-peuple/src/pages/about.tsx +++ b/artifacts/voix-du-peuple/src/pages/about.tsx @@ -1,22 +1,104 @@ import React from "react"; import { Link } from "wouter"; -import { ArrowLeft, Shield, Brain, BookOpen } from "lucide-react"; +import { ArrowLeft, Shield, Brain, BookOpen, Scale, ExternalLink } from "lucide-react"; import { Button } from "@/components/ui/button"; +const TEXTES_SOURCES = [ + { + sigle: "DUDH", + titre: "Déclaration universelle des droits de l'homme", + org: "Organisation des Nations Unies", + annee: "1948", + url: "https://www.un.org/fr/about-us/universal-declaration-of-human-rights", + articles: [ + { num: "Art. 1", texte: "Tous les êtres humains naissent libres et égaux en dignité et en droits. Ils sont doués de raison et de conscience et doivent agir les uns envers les autres dans un esprit de fraternité." }, + { num: "Art. 2", texte: "Chacun peut se prévaloir de tous les droits et de toutes les libertés proclamés dans la présente Déclaration, sans distinction aucune, notamment de race, de couleur, de sexe, de langue, de religion, d'opinion politique ou de toute autre opinion, d'origine nationale ou sociale, de fortune, de naissance ou de toute autre situation." }, + { num: "Art. 19", texte: "Tout individu a droit à la liberté d'opinion et d'expression, ce qui implique le droit de ne pas être inquiété pour ses opinions et celui de chercher, de recevoir et de répandre, sans considérations de frontières, les informations et les idées par quelque moyen d'expression que ce soit." }, + { num: "Art. 20", texte: "Toute propagande en faveur de la guerre est interdite par la loi. Tout appel à la haine nationale, raciale ou religieuse qui constitue une incitation à la discrimination, à l'hostilité ou à la violence est interdit par la loi." }, + ], + }, + { + sigle: "PIDCP", + titre: "Pacte international relatif aux droits civils et politiques", + org: "Organisation des Nations Unies", + annee: "1966", + url: "https://www.ohchr.org/fr/instruments-mechanisms/instruments/international-covenant-civil-and-political-rights", + articles: [ + { num: "Art. 20", texte: "Tout appel à la haine nationale, raciale ou religieuse qui constitue une incitation à la discrimination, à l'hostilité ou à la violence est interdit par la loi." }, + { num: "Art. 25", texte: "Tout citoyen a le droit et la possibilité, sans restrictions déraisonnables, de prendre part à la direction des affaires publiques, soit directement, soit par l'intermédiaire de représentants librement choisis." }, + { num: "Art. 26", texte: "Toutes les personnes sont égales devant la loi et ont droit sans discrimination à une égale protection de la loi." }, + ], + }, + { + sigle: "CEDH", + titre: "Convention européenne des droits de l'homme", + org: "Conseil de l'Europe", + annee: "1950", + url: "https://www.echr.coe.int/european-convention-on-human-rights", + articles: [ + { num: "Art. 10", texte: "Toute personne a droit à la liberté d'expression. Ce droit comprend la liberté d'opinion et la liberté de recevoir ou de communiquer des informations ou des idées sans qu'il puisse y avoir ingérence d'autorités publiques et sans considération de frontière." }, + { num: "Art. 17", texte: "Aucune des dispositions de la présente Convention ne peut être interprétée comme impliquant pour un État, un groupement ou un individu, un droit quelconque de se livrer à une activité ou d'accomplir un acte visant à la destruction des droits ou libertés reconnus dans la présente Convention." }, + ], + }, + { + sigle: "Charte UE", + titre: "Charte des droits fondamentaux de l'Union européenne", + org: "Union européenne", + annee: "2000 / entrée en vigueur 2009", + url: "https://www.europarl.europa.eu/charter/pdf/text_fr.pdf", + articles: [ + { num: "Art. 1", texte: "La dignité humaine est inviolable. Elle doit être respectée et protégée." }, + { num: "Art. 21", texte: "Est interdite toute discrimination fondée notamment sur le sexe, la race, la couleur, les origines ethniques ou sociales, les caractéristiques génétiques, la langue, la religion ou les convictions, les opinions politiques ou toute autre opinion." }, + ], + }, + { + sigle: "Convention génocide", + titre: "Convention pour la prévention et la répression du crime de génocide", + org: "Organisation des Nations Unies", + annee: "1948", + url: "https://www.un.org/fr/genocideprevention/genocide-convention.shtml", + articles: [ + { num: "Art. III (c)", texte: "L'incitation directe et publique à commettre le génocide est punie." }, + ], + }, + { + sigle: "Statut de Rome", + titre: "Statut de Rome de la Cour pénale internationale", + org: "Cour pénale internationale", + annee: "1998", + url: "https://www.icc-cpi.int/sites/default/files/RS-Fra.pdf", + articles: [ + { num: "Art. 7", texte: "On entend par « crime contre l'humanité » l'un quelconque des actes ci-après lorsqu'il est commis dans le cadre d'une attaque généralisée ou systématique lancée contre toute population civile et en connaissance de cette attaque : persécution de tout groupe ou de toute collectivité identifiable pour des motifs d'ordre politique, racial, national, ethnique, culturel ou religieux." }, + ], + }, + { + sigle: "CERD", + titre: "Convention internationale sur l'élimination de toutes les formes de discrimination raciale", + org: "Organisation des Nations Unies", + annee: "1965", + url: "https://www.ohchr.org/fr/instruments-mechanisms/instruments/international-convention-elimination-all-forms-racial", + articles: [ + { num: "Art. 4", texte: "Les États parties condamnent toute propagande et toutes organisations qui s'inspirent d'idées ou de théories fondées sur la supériorité d'une race ou d'un groupe de personnes d'une certaine couleur ou d'une certaine origine ethnique, ou qui prétendent justifier ou encourager toute forme de haine et de discrimination raciales." }, + ], + }, +]; + export default function About() { return (
- +
-

About La Voix du Peuple

+

+ À propos de La Voix du Peuple +

- A digital town square where individual voices forge a collective democratic manifesto, protected by artificial intelligence. + Une place publique numérique où les voix individuelles forment un manifeste démocratique collectif, guidé par le droit international des droits humains.

@@ -24,44 +106,95 @@ export default function About() {
-

The Concept

+

Le concept

- Democracy requires both free expression and a shared foundation of values. "La Voix du Peuple" (The Voice of the People) provides a platform where citizens can submit their ideas for the betterment of society. These distinct, fragile voices are woven together in real-time to create a living, breathing synthesis—a modern digital pamphlet reflecting our collective aspirations. + La démocratie exige à la fois la liberté d'expression et un socle commun de valeurs. Cette plateforme offre aux citoyens un espace pour soumettre leurs idées en faveur d'une société meilleure. Ces voix distinctes sont tissées en temps réel pour former une synthèse vivante — un pamphlet numérique moderne qui reflète nos aspirations collectives.

-

The Democratic Filter

+

Le filtre démocratique

-

- Not all speech serves the public good. To protect the integrity of the agora, an AI agent acts as a civic guardian. Every submitted idea is evaluated against core democratic principles before it can enter the collective synthesis. +

+ Toute prise de parole ne contribue pas nécessairement au bien commun. Pour préserver l'intégrité de l'agora, un agent d'intelligence artificielle agit comme gardien civique. Chaque idée soumise est évaluée à la lumière des droits fondamentaux reconnus par le droit international avant de pouvoir rejoindre la synthèse collective.

-

Protected Values

+

+ Valeurs protégées +

    -
  • Respect for human rights and dignity
  • -
  • Equality and anti-discrimination
  • -
  • Constructive civic discourse (no hate speech or violence)
  • -
  • Commitment to democratic processes
  • +
  • La dignité humaine universelle et inviolable
  • +
  • L'égalité et la non-discrimination
  • +
  • La liberté d'expression dans le respect des droits d'autrui
  • +
  • Le refus de la haine, de la violence et des appels à la persécution
  • +
  • L'attachement aux processus démocratiques et pacifiques
-

- If an idea violates these principles, it is rejected with a clear explanation. This transparency ensures the filter remains accountable to the people it serves. +

+ Lorsqu'une contribution ne peut être retenue, l'auteur en est informé discrètement, sans jugement de sa personne — seulement de la conformité du contenu aux valeurs fondamentales de cet espace commun.

-

The Synthesis

+

La synthèse

- Once accepted, an idea doesn't just sit in a list. A second AI agent constantly reads the stream of accepted ideas and weaves them into a single, cohesive narrative. This text—updated every 15 seconds—represents the prevailing mood, concerns, and hopes of the populace. It is the voice of the people, distilled. + Une idée acceptée ne reste pas isolée. Un second agent lit en continu le flux des idées validées et les tisse en un texte cohérent, éloquent, rédigé à la première personne du pluriel — « Nous, le peuple ». Ce texte, actualisé toutes les 15 secondes, représente l'humeur collective, les préoccupations et les espoirs des citoyens qui ont pris la parole.

+ +
+
+ +

Fondements juridiques

+
+

+ Le filtre s'appuie sur les textes fondateurs du droit international des droits humains. Voici les instruments qui guident chaque décision d'intégration ou de non-intégration d'une contribution. +

+ +
+ {TEXTES_SOURCES.map((source) => ( +
+
+
+ + {source.sigle} + +

{source.titre}

+

+ {source.org} · {source.annee} +

+
+ + + +
+ +
+ {source.articles.map((art) => ( +
+

{art.num}

+

+ « {art.texte} » +

+
+ ))} +
+
+ ))} +
+
diff --git a/artifacts/voix-du-peuple/src/pages/home.tsx b/artifacts/voix-du-peuple/src/pages/home.tsx index e0faf0f..1be02cb 100644 --- a/artifacts/voix-du-peuple/src/pages/home.tsx +++ b/artifacts/voix-du-peuple/src/pages/home.tsx @@ -3,52 +3,90 @@ import { useForm } from "react-hook-form"; import { zodResolver } from "@hookform/resolvers/zod"; import { z } from "zod"; import { format } from "date-fns"; +import { fr } from "date-fns/locale"; import { useQueryClient } from "@tanstack/react-query"; -import { - useSubmitIdea, - useListIdeas, - useGetIdeaStats, +import { + useSubmitIdea, + useListIdeas, + useGetIdeaStats, useGetSynthesis, getListIdeasQueryKey, - getGetIdeaStatsQueryKey + getGetIdeaStatsQueryKey, } from "@workspace/api-client-react"; import { Button } from "@/components/ui/button"; import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "@/components/ui/form"; import { Textarea } from "@/components/ui/textarea"; import { Input } from "@/components/ui/input"; import { ScrollArea } from "@/components/ui/scroll-area"; -import { Separator } from "@/components/ui/separator"; import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert"; -import { Loader2, PenTool, CheckCircle2, XCircle, AlertCircle, TrendingUp, Users } from "lucide-react"; +import { + Accordion, + AccordionContent, + AccordionItem, + AccordionTrigger, +} from "@/components/ui/accordion"; +import { + Loader2, PenTool, CheckCircle2, Info, AlertCircle, TrendingUp, Users, Scale, +} from "lucide-react"; const submitIdeaSchema = z.object({ content: z.string() - .min(10, "Your idea must be at least 10 characters long to carry weight.") - .max(1000, "Brevity is the soul of wit. Keep it under 1000 characters."), + .min(10, "Votre idée doit comporter au moins 10 caractères pour avoir du poids.") + .max(1000, "La concision est une vertu. Restez sous 1 000 caractères."), author: z.string().max(100).optional(), }); type SubmitIdeaValues = z.infer; +const VALEURS = [ + { + source: "DUDH — Art. 1 (ONU, 1948)", + texte: "Tous les êtres humains naissent libres et égaux en dignité et en droits.", + }, + { + source: "DUDH — Art. 19", + texte: "Tout individu a droit à la liberté d'opinion et d'expression.", + }, + { + source: "DUDH — Art. 20", + texte: "Tout appel à la haine nationale, raciale ou religieuse constituant une incitation à la discrimination, à l'hostilité ou à la violence est interdit par la loi.", + }, + { + source: "PIDCP — Art. 20 (ONU, 1966)", + texte: "Tout appel à la haine nationale, raciale ou religieuse qui constitue une incitation à la discrimination, à l'hostilité ou à la violence est interdit par la loi.", + }, + { + source: "CEDH — Art. 10 (Conseil de l'Europe, 1950)", + texte: "Toute personne a droit à la liberté d'expression, sous réserve des restrictions nécessaires à la protection des droits d'autrui.", + }, + { + source: "CEDH — Art. 17", + texte: "Aucune disposition de la Convention ne peut être interprétée comme impliquant le droit de se livrer à une activité visant à la destruction des droits reconnus.", + }, + { + source: "Charte des droits fondamentaux de l'UE — Art. 1 (2000)", + texte: "La dignité humaine est inviolable. Elle doit être respectée et protégée.", + }, +]; + export default function Home() { const queryClient = useQueryClient(); - const [submitResult, setSubmitResult] = React.useState<{ success: boolean; message: string; reason?: string } | null>(null); + const [submitResult, setSubmitResult] = React.useState<{ + success: boolean; + message: string; + reason?: string; + } | null>(null); const submitIdea = useSubmitIdea(); const { data: ideas, isLoading: isLoadingIdeas } = useListIdeas(); const { data: stats } = useGetIdeaStats(); const { data: synthesis, isLoading: isLoadingSynthesis } = useGetSynthesis({ - query: { - refetchInterval: 15000, - } + query: { refetchInterval: 15000 }, }); const form = useForm({ resolver: zodResolver(submitIdeaSchema), - defaultValues: { - content: "", - author: "", - }, + defaultValues: { content: "", author: "" }, }); const onSubmit = (data: SubmitIdeaValues) => { @@ -56,41 +94,41 @@ export default function Home() { submitIdea.mutate({ data }, { onSuccess: (result) => { if (result.accepted) { - setSubmitResult({ - success: true, - message: "Your voice has been added to the collective manifesto." + setSubmitResult({ + success: true, + message: "Votre voix a été intégrée au manifeste collectif.", }); form.reset(); } else { - setSubmitResult({ - success: false, - message: "Your submission was rejected by the democratic filter.", - reason: result.reason + setSubmitResult({ + success: false, + message: "Cette contribution n'a pas pu être intégrée au manifeste car elle n'est pas en accord avec les valeurs fondamentales qui guident cet espace commun.", + reason: result.reason ?? undefined, }); } - - // Invalidate queries to refresh data queryClient.invalidateQueries({ queryKey: getListIdeasQueryKey() }); queryClient.invalidateQueries({ queryKey: getGetIdeaStatsQueryKey() }); }, - onError: (error) => { - setSubmitResult({ - success: false, - message: "An error occurred while submitting your idea. Please try again." + onError: () => { + setSubmitResult({ + success: false, + message: "Une erreur est survenue lors de l'envoi. Veuillez réessayer.", }); - } + }, }); }; return (
- {/* Left Column: Input & Feed */} + {/* Colonne gauche : formulaire + fil des idées */}
-

Speak to the Republic

+

+ Parlez à la République +

- Your voice matters. Submit your vision for the future. + Votre voix compte. Partagez votre vision pour l'avenir.

@@ -101,49 +139,49 @@ export default function Home() { name="content" render={({ field }) => ( - Your Idea + Votre idée -