fix: modification visuel du frontend au niveau du formulaire de contact pour qu'il s'armonise avec le css global.

fix : update du backend avec ajout de la suppression d'un projet.
This commit is contained in:
toine 2025-10-04 11:03:08 +02:00
parent ef1ba911d9
commit 542e00482b
9 changed files with 68 additions and 15 deletions

View file

@ -20,7 +20,7 @@ app.config["API_KEY"] = os.getenv("API_KEY")
@app.route('/')
def get_home():
return jsonify({
"return": "Welcome to API"
"return": f"Welcome to API."
})
app.register_blueprint(projects_bp)

View file

@ -46,3 +46,13 @@ def create_project():
added = add_entry(PROJECTS_FILE, data)
return jsonify(added), 201
@projects_bp.route('/<project_id>', methods=['DELETE'])
def delete_project(project_id):
projects = load_data(PROJECTS_FILE)
project = next((p for p in projects if str(p.get('id')) == project_id), None)
if project:
deleted = delete_entry(PROJECTS_FILE, project_id)
return jsonify(deleted), 200
return jsonify({"error": "Project not found"}), 404

View file

@ -26,8 +26,16 @@ def update_entry(filename, entry_id, new_entry):
return new_entry
return None
def delete_entry(filename, entry_id):
data = load_json(filename)
new_data = [item for item in data if item.get('id') != entry_id]
save_json(filename, new_data)
return len(data) != len(new_data)
def delete_entry(filename, project_id):
# 1. Charger les données
with open(filename, "r", encoding="utf-8") as f:
projects = json.load(f)
# 2. Filtrer pour supprimer le projet avec l'ID donné
updated_projects = [p for p in projects if p.get('id') != int(project_id)]
# 3. Sauvegarder les données mises à jour
with open(filename, "w", encoding="utf-8") as f:
json.dump(updated_projects, f, indent=2, ensure_ascii=False)
return {"status": "success", "deleted_id": project_id}

View file

@ -45,7 +45,7 @@ export default function Header() {
<ul>
<li><Link href="/projects" >Projets</Link></li>
<li><Link href="/competences">Compétences</Link></li>
<li><Link href="#blog">Blog Voyage</Link></li>
<li><Link href="https://toinesensei.itch.io/" target="_blank">Itch.io</Link></li>
<li><Link href="/contact">Contact</Link></li>
<li><Link href="https://fr.malt.be/profile/anthonyviolet1" target="_blank">Malt</Link></li>
<li><Link href="https://www.linkedin.com/in/anthony-violet/" target="_blank">LinkedIn</Link></li>

View file

@ -3,9 +3,12 @@
/* Couleurs de base (clair) */
--color-bg: #ffffff;
--color-surface: #ffffff;
/* Légèrement plus foncé pour champs en clair */
--color-form-surface: color-mix(in oklab, var(--color-surface) 94%, black);
--color-text: #1f2937;
--color-muted: #6b7280;
--color-border: #efefef;
--color-border-strong: #d1d5db;
--color-accent: #ff6b35;
/* Variantes daccent */
@ -43,9 +46,12 @@
:root {
--color-bg: #1f2937;
--color-surface: #0e141b;
/* Légèrement plus clair pour champs en sombre */
--color-form-surface: color-mix(in oklab, var(--color-surface) 92%, white);
--color-text: #e5e7eb;
--color-muted: #9ca3af;
--color-border: #0b0f14;
--color-border-strong: #263241;
/* accent inchangé pour la cohérence de marque */
}
}
@ -54,6 +60,8 @@
html[data-theme="light"] {
--color-bg: #ffffff;
--color-surface: #FFF7F7;
/* Légèrement plus foncé pour champs en clair */
--color-form-surface: color-mix(in oklab, var(--color-surface) 94%, black);
--color-text: #1f2937;
--color-muted: #6b7280;
--color-border: #efefef;
@ -62,6 +70,8 @@ html[data-theme="light"] {
html[data-theme="dark"] {
--color-bg: #1f2937;
--color-surface: #0e141b;
/* Légèrement plus clair pour champs en sombre */
--color-form-surface: color-mix(in oklab, var(--color-surface) 92%, white);
--color-text: #e5e7eb;
--color-muted: #9ca3af;
--color-border: #0b0f14;

View file

@ -15,12 +15,13 @@ select,
textarea {
width: 100%;
max-width: 640px;
background: #ffffff;
background: var(--color-form-surface, var(--color-surface, #ffffff));
color: var(--color-text, #1f2937);
border: 1px solid var(--color-border, #efefef);
border: 1px solid var(--color-border-strong, #d1d5db);
border-radius: var(--radius-sm, 6px);
padding: 0.625rem 0.75rem;
outline: none;
box-shadow: var(--shadow-sm, 0 1px 2px rgba(0, 0, 0, 0.06));
transition: border-color 0.2s ease, box-shadow 0.2s ease, background-color 0.2s ease;
}
@ -28,6 +29,8 @@ input:hover,
select:hover,
textarea:hover {
border-color: var(--color-accent-100, #ffe4d6);
background: color-mix(in oklab, var(--color-surface, #ffffff) 94%, var(--color-accent-50, #fff4ec));
box-shadow: var(--shadow-md, 0 2px 10px rgba(0, 0, 0, 0.08));
}
textarea {
@ -45,7 +48,7 @@ select:focus,
textarea:focus {
border-color: var(--color-accent, #ff6b35);
box-shadow: 0 0 0 3px color-mix(in oklab, var(--color-accent, #ff6b35) 22%, transparent);
background: #fff;
background: var(--color-form-surface, var(--color-surface, #ffffff));
}
/* Boutons */

View file

@ -121,6 +121,10 @@ hr {
color: var(--color-muted, #6b7280);
}
footer {
background: var(--color-surface);
}
/* Fin: préférences de mouvement */
@media (prefers-reduced-motion: reduce) {
* {
@ -129,3 +133,21 @@ hr {
scroll-behavior: auto !important;
}
}
/* Sticky footer (hidden at top, visible on scroll) */
.sticky-footer {
position: fixed;
left: 0;
right: 0;
bottom: 0;
transform: translateY(100%);
transition: transform 0.3s ease;
z-index: 40;
pointer-events: none; /* prevent blocking clicks when hidden */
}
.sticky-footer.is-visible {
transform: translateY(0);
box-shadow: 0 -6px 20px rgba(0, 0, 0, 0.08);
pointer-events: auto;
}

View file

@ -9,6 +9,7 @@ import "./css/links.css";
import type { ReactNode } from "react";
import Header from "./components/Header";
import Footer from "./components/Footer";
export default function RootLayout({ children }: { children: ReactNode }) {
return (
@ -17,9 +18,7 @@ export default function RootLayout({ children }: { children: ReactNode }) {
<Header />
<main>{children}</main>
<footer>
<p>© 2025 - Toine</p>
</footer>
<Footer />
</body>
</html>
);

View file

@ -67,6 +67,7 @@ export default function NewProjectPage() {
</select>
) : (
<input
type={key === "url" || key === "image" || key === "source" ? "url" : "text"}
name={key}
value={formData[key as keyof typeof formData]}
onChange={handleChange}