diff --git a/Dockerfile b/Dockerfile index 193b26c..3da4b65 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,34 +1,26 @@ -# === Étape 1 : Build === -FROM node:20-alpine AS builder - +FROM node:22-alpine AS calculatrice-base WORKDIR /app +ENV NEXT_TELEMETRY_DISABLED=1 -# Copier les fichiers de dépendances pour profiter du cache Docker -COPY package*.json ./ - -# Installer uniquement ce qu'il faut pour le build +FROM calculatrice-base AS calculatrice-deps +COPY package.json package-lock.json ./ RUN npm ci -# Copier tout le code +FROM calculatrice-deps AS calculatrice-dev COPY . . +EXPOSE 3000 +CMD ["npm", "run", "dev", "--", "--hostname", "0.0.0.0", "--port", "3000"] -# Build Next.js pour la production +FROM calculatrice-deps AS calculatrice-builder +COPY . . RUN npm run build -# === Étape 2 : Runner léger === -FROM node:20-alpine AS runner - -WORKDIR /app - -# Copier uniquement ce qui est nécessaire pour la prod -COPY --from=builder /app/package*.json ./ -COPY --from=builder /app/node_modules ./node_modules -COPY --from=builder /app/.next ./.next -COPY --from=builder /app/public ./public - -# Mode production +FROM calculatrice-base AS calculatrice-runner ENV NODE_ENV=production +ENV HOSTNAME=0.0.0.0 +ENV PORT=3000 +COPY --from=calculatrice-builder /app/.next/standalone ./ +COPY --from=calculatrice-builder /app/.next/static ./.next/static +COPY --from=calculatrice-builder /app/public ./public EXPOSE 3000 - -# Lancer le serveur Next.js -CMD ["npm", "start"] \ No newline at end of file +CMD ["node", "server.js"] \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..e73322f --- /dev/null +++ b/LICENSE @@ -0,0 +1,25 @@ +Copyright (c) 2026 Arthur + +Licence pour tous les projets Arthur + +1. Définition +Cette licence définit les droits et obligations concernant l'utilisation, la modification et la redistribution du code fourni par l'auteur. + +2. Autorisation d'utilisation +Vous êtes libre d'utiliser ce code pour vos projets personnels ou commerciaux. L'utilisation doit inclure une mention de l'auteur d’une manière libre (ex: "inspiré de ArthurP"). + +3. Modification +Vous pouvez modifier, adapter ou améliorer le code pour vos besoins. Les modifications doivent être identifiées comme telles et ne doivent pas être présentées comme l'original. + +4. Redistribution +- Le code original **ne peut pas être redistribué tel quel**. +- Les versions modifiées peuvent être partagées, sous réserve de mentionner l'auteur original. + +5. Usage commercial +L’usage commercial des versions modifiées est autorisé. Vous pouvez générer des revenus avec votre version modifiée. + +6. Attribution +L'auteur original doit être cité d’une manière libre, mais visible, sur tout projet utilisant ce code ou ses dérivés. + +7. Responsabilité +Le code est fourni "tel quel", sans garantie d’aucune sorte. L’auteur décline toute responsabilité pour tout dommage direct ou indirect résultant de l’utilisation du code. \ No newline at end of file diff --git a/README.md b/README.md index b4d571a..2973696 100644 --- a/README.md +++ b/README.md @@ -1,33 +1,32 @@ # Calculatrice -Application web de calculatrice réalisée avec Next.js. +Calculatrice web (simple + scientifique) construite avec Next.js. -## Site en ligne +## Liens -- Projet: https://calculatrice.arthurp.fr +- Site: https://calculatrice.arthurp.fr +- Site principal: https://arthurp.fr +- Contact: https://contact.arthurp.fr +- Email: contact@arthurp.fr -## Objectif - -Proposer une calculatrice simple, rapide et responsive, utilisable sur desktop et mobile. - -## Stack technique +## Stack - Next.js 16 - React 19 - TypeScript -## Lancement en local +## Developpement local -Prerequis: Node.js 20+ +Prerequis: Node.js 22+ ```bash -npm install +npm ci npm run dev ``` -Application accessible sur http://localhost:3000 +Application: http://localhost:3000 -## Scripts utiles +## Scripts ```bash npm run dev @@ -36,21 +35,24 @@ npm run start npm run lint ``` -## Deploiement +## Docker -Build de production: +Mode dev: ```bash -npm run build +docker compose --profile dev up --build ``` -Ensuite deployer sur votre plateforme cible (Vercel, VPS, etc.). +Mode production: -## Backlinks +```bash +docker compose --profile prod up --build -d +``` -- Calculatrice en ligne: https://calculatrice.arthurp.fr -- Site principal: https://arthurp.fr +- Dev: http://localhost:3000 +- Prod: http://localhost:3014 -## Licence +## Pages legales -Projet personnel. +- /mentions-legales +- /politique-de-confidentialite diff --git a/app/components/Calculator.tsx b/app/components/Calculator.tsx index 36f4d25..a509eaf 100644 --- a/app/components/Calculator.tsx +++ b/app/components/Calculator.tsx @@ -1,5 +1,6 @@ "use client"; +import Link from "next/link"; import { useState, useEffect, useCallback, useRef } from "react"; /* ══════════════════════════════════════════════ @@ -151,39 +152,37 @@ export default function Calculator() { const [error, setError] = useState(""); // Message d'erreur const [steps, setSteps] = useState([]); // Étapes de calcul const [showSteps, setShowSteps] = useState(false); // Afficher les étapes - const [history, setHistory] = useState([]); // Historique + const [history, setHistory] = useState(() => { + if (typeof window === "undefined") return []; + try { + const savedHistory = localStorage.getItem(HISTORY_KEY); + return savedHistory ? JSON.parse(savedHistory) : []; + } catch { + return []; + } + }); // Historique const [showHistory, setShowHistory] = useState(false); // Panneau historique visible const [isScientific, setIsScientific] = useState(false); // Mode scientifique - const [isDark, setIsDark] = useState(false); // Thème sombre + const [isDark, setIsDark] = useState(() => { + if (typeof window === "undefined") return false; + try { + const savedTheme = localStorage.getItem(THEME_KEY); + if (savedTheme === "dark") return true; + if (savedTheme === "light") return false; + return window.matchMedia("(prefers-color-scheme: dark)").matches; + } catch { + return false; + } + }); // Thème sombre const [copied, setCopied] = useState(false); // Feedback copie const [lastKey, setLastKey] = useState(""); // Dernière touche pressée (feedback visuel) const displayRef = useRef(null); - const simpleRef = useRef(null); - const sciRef = useRef(null); - // ── Chargement initial depuis localStorage ── + // ── Synchroniser la classe de thème avec l'état courant ── useEffect(() => { - try { - const savedHistory = localStorage.getItem(HISTORY_KEY); - if (savedHistory) setHistory(JSON.parse(savedHistory)); - - const savedTheme = localStorage.getItem(THEME_KEY); - if (savedTheme === "dark") { - setIsDark(true); - document.documentElement.classList.add("dark"); - } else if (savedTheme === "light") { - setIsDark(false); - document.documentElement.classList.remove("dark"); - } else { - // Détecter la préférence système - const prefersDark = window.matchMedia("(prefers-color-scheme: dark)").matches; - setIsDark(prefersDark); - } - } catch { - // localStorage non disponible - } - }, []); + document.documentElement.classList.toggle("dark", isDark); + }, [isDark]); // ── Sauvegarder l'historique dans localStorage ── useEffect(() => { @@ -430,7 +429,7 @@ export default function Calculator() { ════════════════════════════════════════════ */ return ( -
+ )} - {/* ── Footer SEO avec contenu sémantique ── */} -
- {/* Contenu textuel riche pour le SEO */} -
-

- Calculatrice en ligne gratuite -

-

- Notre calculatrice en ligne gratuite vous permet d'effectuer tous vos calculs - directement dans votre navigateur, sans installation ni inscription. Que vous ayez - besoin d'une simple addition ou d'un calcul scientifique complexe avec des - fonctions trigonométriques, notre outil s'adapte à vos besoins. -

+ {/* ── Contenu SEO ── */} +
+

+ Calculatrice en ligne simple et scientifique +

+

+ Cette calculatrice en ligne gratuite permet de faire vos opérations du quotidien et vos calculs plus avances, + directement depuis votre navigateur. Aucun compte, aucune installation et une interface rapide sur mobile comme + sur ordinateur. +

+

+ Le mode simple couvre addition, soustraction, multiplication et division. Le mode scientifique ajoute sin, cos, + tan, logarithmes, racine carree, puissances, factorielle et constantes pi / e. L'historique est conserve + localement pour retrouver vos derniers calculs. +

-

- Mode simple : les opérations essentielles -

-

- Le mode simple couvre les quatre opérations fondamentales : addition (+), - soustraction (−), multiplication (×) et division (÷). Vous pouvez utiliser - des parenthèses pour structurer vos expressions et obtenir des résultats - précis. La gestion des erreurs vous avertit automatiquement en cas de - division par zéro. -

- -

- Mode scientifique : des fonctions avancées -

-

- Basculez en mode scientifique pour accéder aux fonctions trigonométriques - (sinus, cosinus, tangente), aux logarithmes (log décimal, logarithme naturel), - à la racine carrée, aux puissances, à la factorielle, ainsi qu'aux - constantes mathématiques π et e. Idéal pour les étudiants, ingénieurs et - professionnels. -

-
- - {/* Section FAQ pour le SEO */} -
-

- Questions fréquentes -

-
+
+

+ Questions frequentes +

+
{[ { - q: "Comment utiliser la calculatrice en ligne ?", - a: "Cliquez sur les boutons ou utilisez votre clavier pour saisir une expression mathématique, puis appuyez sur « = » ou Entrée pour obtenir le résultat.", + q: "Comment faire un calcul rapidement ?", + a: "Saisissez votre expression puis appuyez sur Entree ou sur le bouton =.", }, { - q: "Quelles fonctions scientifiques sont disponibles ?", - a: "Sinus, cosinus, tangente, logarithme décimal, logarithme naturel, racine carrée, puissances, factorielle, et les constantes π et e.", + q: "Puis-je utiliser le clavier ?", + a: "Oui. Les chiffres et operateurs sont pris en charge. Entree calcule, Echap efface et Retour arriere supprime le dernier caractere.", }, { - q: "L'historique des calculs est-il sauvegardé ?", - a: "Oui, vos 50 derniers calculs sont sauvegardés automatiquement dans votre navigateur et persistent même après fermeture de la page.", + q: "A quoi sert le mode scientifique ?", + a: "Il ajoute les fonctions avancees: sin, cos, tan, log, ln, racine carree, puissances et factorielle.", }, { - q: "La calculatrice est-elle vraiment gratuite ?", - a: "Oui, 100 % gratuite, sans publicité et sans inscription. Utilisez-la autant que vous le souhaitez.", + q: "Est-ce que l'historique est conserve ?", + a: "Oui, les 50 derniers calculs sont stockes localement dans votre navigateur.", }, { - q: "Puis-je utiliser des raccourcis clavier ?", - a: "Oui ! Chiffres et opérateurs au clavier, Entrée pour calculer, Échap pour effacer, Retour arrière pour supprimer, Ctrl+C pour copier.", + q: "Puis-je reutiliser un ancien calcul ?", + a: "Oui, ouvrez l'historique puis cliquez sur une ligne pour recharger l'expression et le resultat.", }, - ].map((faq, i) => ( + { + q: "La calculatrice fonctionne-t-elle sur mobile ?", + a: "Oui, l'interface est adaptee aux ecrans mobiles et ordinateurs.", + }, + { + q: "Dois-je creer un compte ?", + a: "Non, aucun compte n'est necessaire pour utiliser la calculatrice.", + }, + { + q: "Comment contacter le proprietaire du site ?", + a: "Via contact.arthurp.fr ou par email a contact@arthurp.fr.", + }, + ].map((item, i) => (
- - {faq.q} + + {item.q} -

- {faq.a} -

+

{item.a}

))}
-
+
+ - {/* Copyright */} -
-

© {new Date().getFullYear()} Calculatrice en ligne gratuite — Simple & Scientifique

-

- Outil de calcul en ligne rapide, gratuit et sans inscription. -

+ {/* ── Footer normal en bas de page ── */} +
diff --git a/app/globals.css b/app/globals.css index 75becaa..8af73ba 100644 --- a/app/globals.css +++ b/app/globals.css @@ -285,6 +285,7 @@ body { .mode-toggle { position: relative; display: flex; + min-width: 210px; background: var(--surface); border: 1px solid var(--border-color); border-radius: 10px; @@ -292,9 +293,11 @@ body { } .mode-toggle button { + flex: 1; position: relative; z-index: 1; padding: 6px 16px; + text-align: center; font-size: 0.85rem; font-weight: 500; color: var(--muted); @@ -311,10 +314,12 @@ body { .mode-slider { position: absolute; top: 2px; + left: 2px; bottom: 2px; + width: calc(50% - 2px); border-radius: 8px; background: var(--primary); - transition: left 0.3s ease, width 0.3s ease; + transition: transform 0.3s ease; } /* ══════════════════════════════════════════════ diff --git a/app/mentions-legales/page.tsx b/app/mentions-legales/page.tsx new file mode 100644 index 0000000..8d5f92a --- /dev/null +++ b/app/mentions-legales/page.tsx @@ -0,0 +1,34 @@ +import type { Metadata } from "next"; + +export const metadata: Metadata = { + title: "Mentions legales", + description: "Mentions legales du site calculatrice.arthurp.fr", +}; + +export default function MentionsLegalesPage() { + return ( +
+
+

Mentions legales

+ +
+

+ Site: calculatrice.arthurp.fr +

+

+ Proprietaire et editeur: Arthur P. +

+

+ Contact principal: contact.arthurp.fr +

+

+ Email: contact@arthurp.fr +

+

+ Hebergement: infrastructure auto-hebergee sur Proxmox. +

+
+
+
+ ); +} diff --git a/app/politique-de-confidentialite/page.tsx b/app/politique-de-confidentialite/page.tsx new file mode 100644 index 0000000..a127e23 --- /dev/null +++ b/app/politique-de-confidentialite/page.tsx @@ -0,0 +1,31 @@ +import type { Metadata } from "next"; + +export const metadata: Metadata = { + title: "Politique de confidentialite", + description: "Politique de confidentialite du site calculatrice.arthurp.fr", +}; + +export default function PolitiqueConfidentialitePage() { + return ( +
+
+

Politique de confidentialite

+ +
+

+ Cette application ne requiert pas de compte et ne collecte pas de donnees personnelles cote serveur pour son fonctionnement courant. +

+

+ L'historique de calcul est stocke localement dans votre navigateur (localStorage) pour ameliorer l'experience utilisateur. +

+

+ Vous pouvez supprimer ces donnees a tout moment depuis le bouton "Tout effacer" dans l'historique ou via les reglages de votre navigateur. +

+

+ Pour toute demande, vous pouvez utiliser contact.arthurp.fr ou contact@arthurp.fr. +

+
+
+
+ ); +} diff --git a/app/sitemap.ts b/app/sitemap.ts index 47c5fef..2f42081 100644 --- a/app/sitemap.ts +++ b/app/sitemap.ts @@ -15,5 +15,17 @@ export default function sitemap(): MetadataRoute.Sitemap { changeFrequency: "monthly", priority: 1.0, }, + { + url: `${baseUrl}/mentions-legales`, + lastModified: new Date(), + changeFrequency: "yearly", + priority: 0.4, + }, + { + url: `${baseUrl}/politique-de-confidentialite`, + lastModified: new Date(), + changeFrequency: "yearly", + priority: 0.4, + }, ]; } diff --git a/docker-compose.yml b/docker-compose.yml index a47d63b..37aea8c 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,11 +1,31 @@ services: - web: - build: . + calculatrice-dev: + profiles: ["dev"] + build: + context: . + target: calculatrice-dev + container_name: calculatrice-dev ports: - "3000:3000" volumes: - - ./:/app + - .:/app - /app/node_modules + - /app/.next environment: - - NODE_ENV=development - command: npm run dev \ No newline at end of file + NEXT_TELEMETRY_DISABLED: "1" + NODE_ENV: development + + calculatrice-prod: + profiles: ["prod"] + build: + context: . + target: calculatrice-runner + container_name: calculatrice-prod + restart: unless-stopped + ports: + - "3014:3000" + env_file: + - .env + environment: + NEXT_TELEMETRY_DISABLED: "1" + NODE_ENV: production \ No newline at end of file