-
-
Notifications
You must be signed in to change notification settings - Fork 0
Update homepage #325
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Update homepage #325
Changes from all commits
e885a7f
13b6ec7
46da974
558bf70
253c804
d9a62f3
1758418
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,37 @@ | ||
| { | ||
| // - Git | ||
| "git.autofetch": true, | ||
|
|
||
| // - TypeScript | ||
| "typescript.updateImportsOnFileMove.enabled": "always", | ||
|
|
||
| // - Actions on save | ||
| "editor.codeActionsOnSave": { | ||
| "source.fixAll.eslint": "always" | ||
| }, | ||
|
|
||
| // - Lint and format | ||
| "editor.formatOnSave": true, | ||
| "eslint.format.enable": true, | ||
| "eslint.validate": [ | ||
| "javascript" | ||
| ], | ||
| "[typescript]": { | ||
| "editor.defaultFormatter": "esbenp.prettier-vscode" | ||
| }, | ||
| "[typescriptreact]": { | ||
| "editor.defaultFormatter": "esbenp.prettier-vscode" | ||
| }, | ||
| "[javascript]": { | ||
| "editor.defaultFormatter": "esbenp.prettier-vscode" | ||
| }, | ||
| "[json]": { | ||
| "editor.defaultFormatter": "esbenp.prettier-vscode" | ||
| }, | ||
| "[css]": { | ||
| "editor.defaultFormatter": "stylelint.vscode-stylelint" | ||
| }, | ||
|
|
||
| // - Common | ||
| "editor.tabSize": 2, | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,124 @@ | ||
| import React from "react"; | ||
| import Image from "next/image"; | ||
|
|
||
| // Données extraites pour éviter la répétition | ||
| const reviewsData = [ | ||
| { | ||
| id: 1, | ||
| text: "Composé de talents variés, allant de développeurs à des designers passionnés. Chacun apporte sa touche unique à nos projets. Ensemble, nous formons un collectif où l'innovation est au cœur de tout ce que nous entreprenons.", | ||
| author: "Cécile Pislor", | ||
| role: "CEO @ DroitAuCoeurCoaching", | ||
| avatar: "/favicon-32x32.png", | ||
| }, | ||
| { | ||
| id: 2, | ||
| text: "Composé de talents variés, allant de développeurs à des designers passionnés. Chacun apporte sa touche unique à nos projets. Ensemble, nous formons un collectif où l'innovation est au cœur de tout ce que nous entreprenons.", | ||
| author: "Cécile Pislor", | ||
| role: "CEO @ DroitAuCoeurCoaching", | ||
| avatar: "/favicon-32x32.png", | ||
| }, | ||
| { | ||
| id: 3, | ||
| text: "Composé de talents variés, allant de développeurs à des designers passionnés. Chacun apporte sa touche unique à nos projets. Ensemble, nous formons un collectif où l'innovation est au cœur de tout ce que nous entreprenons.", | ||
| author: "Cécile Pislor", | ||
| role: "CEO @ DroitAuCoeurCoaching", | ||
| avatar: "/favicon-32x32.png", | ||
| }, | ||
| ]; | ||
|
|
||
| const Reviews: React.FC = () => { | ||
| return ( | ||
| <section className="pt-[15em] py-16 px-4 relative min-h-screen"> | ||
| <div className="max-w-7xl mx-auto relative"> | ||
| {/* Titre sticky qui reste derrière les commentaires */} | ||
| <div className="sticky top-20 text-center z-0 mb-16"> | ||
| <h2 className="text-black font-semibold text-4xl mb-4 pointer-events-none"> | ||
| Ce que nos experts disent de nous. | ||
| </h2> | ||
| <p className="text-gray-600 text-lg pointer-events-none"> | ||
| On ne les a pas du tout forcés à parler. | ||
| </p> | ||
| </div> | ||
|
|
||
| {/* Grille des avis qui défile devant le titre */} | ||
| <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8 relative z-10"> | ||
| {reviewsData.map((review, index) => { | ||
| const getTransform = (index: number) => { | ||
| switch (index) { | ||
| case 0: | ||
| return "translate-y-0"; | ||
| case 1: | ||
| return "translate-y-[30rem]"; | ||
| case 2: | ||
| return "translate-y-32"; | ||
| default: | ||
| return "translate-y-0"; | ||
| } | ||
| }; | ||
|
|
||
| return ( | ||
| <article | ||
| key={review.id} | ||
| className={`bg-white rounded-lg p-6 shadow-sm hover:shadow-md transition-all duration-300 ${getTransform(index)} z-10 relative`} | ||
| > | ||
| <blockquote className="mb-6"> | ||
| <p className="text-gray-700 italic leading-relaxed"> | ||
| “{review.text}” | ||
| </p> | ||
| </blockquote> | ||
| <div className="flex items-center gap-4"> | ||
| <Image | ||
| src={review.avatar} | ||
| alt={`Photo de ${review.author}`} | ||
| width={60} | ||
| height={60} | ||
| className="rounded-full" | ||
| /> | ||
| <div> | ||
| <h3 className="font-semibold text-lg text-gray-900"> | ||
| {review.author} | ||
| </h3> | ||
| <p className="text-sm text-gray-600">{review.role}</p> | ||
| </div> | ||
| </div> | ||
| </article> | ||
| ); | ||
| })} | ||
| </div> | ||
|
|
||
| {/* Spacer pour que les cartes aient assez d'espace ET pour révéler le titre à la fin */} | ||
| <div className="h-[40rem]"></div> | ||
| </div> | ||
|
|
||
| {/* Témoignage Lucas Bodin */} | ||
| <div className="max-w-7xl mx-auto px-4 py-16 gap-8"> | ||
| <div className="flex justify-center items-center gap-16 max-w-5xl mx-auto"> | ||
| <Image | ||
| src="/static/images/members/lucas-bodin.jpg" | ||
| alt="Photo Lucas" | ||
| width={150} | ||
| height={150} | ||
| className="rounded-lg rotate-[-15deg] shadow-lg bg-white px-2 pt-2 pb-6 transition-all duration-300 ease-in-out hover:rotate-0 hover:scale-105" | ||
| /> | ||
| <div className="flex-1"> | ||
| <p className="text-2xl md:text-3xl font-medium text-black leading-relaxed mb-6"> | ||
| “onRuntime Studio c’est bien plus qu’un simple | ||
| studio de créateurs. C’est un espace où l’innovation, | ||
| la collaboration, et la passion se lient pour donner vie à des | ||
| projets uniques. Nous croyons au pouvoir de l’intelligence | ||
| collective, où chaque créateur, apporte sa vision afin | ||
| qu’ensemble, nous transformions des idées en | ||
| réalités.” | ||
| </p> | ||
| <p className="text-lg text-gray-600"> | ||
| Lucas Bodin, Head of Design @{" "} | ||
| <strong className="text-black">onRuntime Studio</strong> | ||
| </p> | ||
| </div> | ||
| </div> | ||
| </div> | ||
| </section> | ||
| ); | ||
| }; | ||
|
|
||
| export default Reviews; |
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,118 @@ | ||||||||||
| 'use client'; | ||||||||||
|
|
||||||||||
| import React, { useEffect, useRef, useState } from 'react'; | ||||||||||
| import Link from 'next/link'; | ||||||||||
|
|
||||||||||
| const colorSets = [ | ||||||||||
| { | ||||||||||
| text: 'text-black', | ||||||||||
| button: 'bg-black text-white', | ||||||||||
| }, | ||||||||||
| { | ||||||||||
| text: 'text-[#652599]', | ||||||||||
| button: 'bg-[#652599] text-white', | ||||||||||
| }, | ||||||||||
| { | ||||||||||
| text: 'text-[#23cd82]', | ||||||||||
| button: 'bg-[#23cd82] text-white', | ||||||||||
| }, | ||||||||||
| { | ||||||||||
| text: 'text-[#ee2400]', | ||||||||||
| button: 'bg-[#ee2400] text-white', | ||||||||||
| }, | ||||||||||
| ]; | ||||||||||
|
|
||||||||||
| const services = [ | ||||||||||
| { | ||||||||||
| color: '#652599', | ||||||||||
| title: 'Design UX UI/Branding', | ||||||||||
| description: | ||||||||||
| 'Moodboard, maquettage UI complet, prototypage et identité graphique faite maison.', | ||||||||||
| }, | ||||||||||
| { | ||||||||||
| color: '#23cd82', | ||||||||||
| title: 'Développement Front & Back End', | ||||||||||
| description: | ||||||||||
| 'Développement from-scratch côté front (web, app) et back (API, bots).', | ||||||||||
| }, | ||||||||||
| { | ||||||||||
| color: '#ee2400', | ||||||||||
| title: 'Intégrations Web', | ||||||||||
| description: | ||||||||||
| 'Création ou adaptation de projets avec Wordpress, Shopify, Webflow, etc.', | ||||||||||
| }, | ||||||||||
| ]; | ||||||||||
|
|
||||||||||
| const Services: React.FC = () => { | ||||||||||
| const [colorIndex, setColorIndex] = useState(0); | ||||||||||
| const containerRef = useRef<HTMLDivElement | null>(null); | ||||||||||
|
|
||||||||||
| useEffect(() => { | ||||||||||
| const handleScroll = () => { | ||||||||||
| if (!containerRef.current) return; | ||||||||||
|
|
||||||||||
| const containerTop = containerRef.current.getBoundingClientRect().top + window.scrollY; | ||||||||||
| const scrollY = window.scrollY; | ||||||||||
| const earlyOffset = 25; | ||||||||||
| const relativeY = scrollY - containerTop + earlyOffset; | ||||||||||
|
|
||||||||||
| const sectionHeight = 300; | ||||||||||
| let index = Math.floor(relativeY / sectionHeight); | ||||||||||
| index = Math.max(0, Math.min(index, colorSets.length - 1)); | ||||||||||
|
||||||||||
| index = Math.max(0, Math.min(index, colorSets.length - 1)); | |
| index = Math.max(0, Math.min(index, services.length - 1)); |
Copilot
AI
Jun 25, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Throttling or debouncing the scroll handler would improve performance by reducing the number of state updates during rapid scrolling.
Copilot
AI
Jun 25, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using the array index as a key can cause rendering issues if items ever change order. Consider using a unique property (e.g., service.title) or adding an explicit id field.
| {services.map((service, index) => ( | |
| <div key={index} style={{ minHeight: '300px' }}> | |
| {services.map((service) => ( | |
| <div key={service.id} style={{ minHeight: '300px' }}> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| import React from "react"; | ||
| import Link from 'next/link'; | ||
| import Image from 'next/image'; | ||
|
|
||
| const Tonightpass: React.FC = () => { | ||
| return( | ||
| <div className="flex flex-col items-center h-auto min-h-screen bg-black pt-16"> | ||
| <div className="sticky top-20 z-50"> | ||
| <Link href="/projects/tonightpass"> | ||
| <button className="bg-white text-black px-6 py-2 rounded-md shadow hover:bg-gray-100"> | ||
| Notre success story 🏆 | ||
| </button> | ||
| </Link> | ||
| </div> | ||
| <h2 className="text-white font-semibold text-center mt-8 text-4xl">Tonight Pass, <br /> la billetterie 2.0</h2> | ||
| <p className="text-white text-center mt-8">Réservez votre entrée, entrez rapidement, <br />restez en contact avec les gens.</p> | ||
| <strong className="text-white text-center mt-8">En quelques clics depuis votre canapé 🛋️</strong> | ||
| <Link href="/projects/tonightpass"> | ||
| <button className="mt-8 bg-white text-black px-6 py-2 rounded-md shadow hover:bg-gray-100"> | ||
| En savoir plus | ||
| </button> | ||
| </Link> | ||
| <div className="w-full max-w-screen-lg mt-8 mb-8"> | ||
| <Image | ||
| src="/static/images/projects/tonightpass/showcase.jpg" | ||
| alt="Showcase Tonight Pass" | ||
| width={1000} | ||
| height={800} | ||
| className="w-full h-auto rounded-md" | ||
| /> | ||
| </div> | ||
| </div> | ||
| ) | ||
| }; | ||
|
|
||
| export default Tonightpass; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This SVG is purely decorative; add
aria-hidden="true"to hide it from assistive technologies.