Compare commits

..
5 Commits
5 changed files with 56 additions and 4 deletions

No files matched your search

+1 -1
View File
@@ -67,7 +67,7 @@ Ou avec les commandes Docker :
```bash
docker build -t notes .
docker run -d --name notes -p 8080:80 notes
docker run -d --rm --name notes -p 8080:80 notes
```
L'app sera accessible sur http://localhost:8080.
+52
View File
@@ -0,0 +1,52 @@
# Notes
Application de prise de notes personnelle sous forme de SPA PWA (React + TypeScript + Tailwind CSS).
Installable, utilisable hors connexion, et 100 % privée : les données restent dans le **localStorage** du navigateur, sans partage ni transmission à un serveur externe.
## Fonctionnalités
- Créer, lire, modifier et supprimer des notes
- Données stockées localement (localStorage) — aucune donnée partagée ni transmise
- PWA installable avec mode hors connexion
- Design responsive mobile-first
- Modale RGPD, confirmation avant suppression, page d'erreur 404
## Utilisation
L'image est servie par nginx et exposée sur le port 80.
### Docker
```bash
docker run -d --rm --name notes -p 8080:80 devcodetools/notes:latest
```
Accédez ensuite à l'application sur http://localhost:8080.
### Docker Compose
```yaml
services:
notes:
image: devcodetools/notes:latest
container_name: notes
restart: unless-stopped
ports:
- "8080:80"
```
Puis :
```bash
docker compose up -d
```
## Construction depuis les sources
```bash
docker build -t devcodetools/notes:latest .
```
## Confidentialité
Vos notes ne quittent jamais votre appareil : stockage uniquement dans le localStorage de votre navigateur, aucune donnée partagée avec des tiers, aucune transmission vers un serveur.
+1 -1
View File
@@ -39,7 +39,7 @@ function App() {
}
return (
<main className="mx-auto flex w-full max-w-2xl min-h-dvh flex-col pb-[calc(env(safe-area-inset-bottom)+7rem)]">
<main className="mx-auto flex w-full max-w-3xl min-h-dvh flex-col pb-[calc(env(safe-area-inset-bottom)+7rem)]">
<header className="sticky top-0 z-10 border-b border-gray-200 bg-white/95 px-4 pb-3 pt-[calc(env(safe-area-inset-top)+0.75rem)] backdrop-blur">
<div className="flex h-11 items-center gap-1">
{creating || selectedNote ? (
+1 -1
View File
@@ -6,7 +6,7 @@ function ErrorPage({
message = "Désolé, la page que vous cherchez n'existe pas.",
}: ErrorPageProps) {
return (
<main className="mx-auto flex w-full max-w-2xl min-h-dvh flex-col items-center justify-center gap-6 px-4 text-center">
<main className="mx-auto flex w-full max-w-3xl min-h-dvh flex-col items-center justify-center gap-6 px-4 text-center">
<p className="text-6xl font-bold text-blue-700">{code}</p>
<div>
<h1 className="text-2xl font-semibold">{title}</h1>
+1 -1
View File
@@ -13,7 +13,7 @@ describe('RgpdInfo', () => {
render(<RgpdInfo open onClose={vi.fn()} />)
expect(screen.getByRole('dialog', { name: 'Protection des données (RGPD)' })).toBeInTheDocument()
expect(screen.getByText('localStorage', { exact: false })).toBeInTheDocument()
expect(screen.getByText(/stockage local/i)).toBeInTheDocument()
expect(
screen.getByText(/ne sont jamais partagées avec des tiers/i),
).toBeInTheDocument()