From 07a66948837482f676c1703e39ce9168244cd4a8 Mon Sep 17 00:00:00 2001 From: kbe Date: Sun, 17 Aug 2025 23:47:07 +0200 Subject: [PATCH] chore: Counter now embedded with Stimulus Before this commit, Counter js was autonomous. Now it's registered like a controller in Stimulus. --- app/javascript/application.js | 13 ---- app/javascript/components/counter.js | 61 ------------------- .../controllers/counter_controller.js | 59 ++++++++++++++++++ .../controllers/hello_controller.js | 7 --- app/javascript/controllers/index.js | 4 +- app/views/pages/home.html.erb | 14 ++--- 6 files changed, 68 insertions(+), 90 deletions(-) delete mode 100644 app/javascript/components/counter.js delete mode 100644 app/javascript/controllers/hello_controller.js diff --git a/app/javascript/application.js b/app/javascript/application.js index 758b72d..d933293 100644 --- a/app/javascript/application.js +++ b/app/javascript/application.js @@ -1,16 +1,3 @@ // Entry point for the build script in your package.json import "@hotwired/turbo-rails" import "./controllers" -import Counter from "./components/counter" - -// Initialize counters when DOM is ready -document.addEventListener('DOMContentLoaded', () => { - const counters = document.querySelectorAll('.counter') - counters.forEach(counter => new Counter(counter)) -}) - -// Re-initialize counters on Turbo page loads -document.addEventListener('turbo:load', () => { - const counters = document.querySelectorAll('.counter') - counters.forEach(counter => new Counter(counter)) -}) diff --git a/app/javascript/components/counter.js b/app/javascript/components/counter.js deleted file mode 100644 index 5452a54..0000000 --- a/app/javascript/components/counter.js +++ /dev/null @@ -1,61 +0,0 @@ -export default class Counter { - constructor(element) { - this.element = element - this.target = parseFloat(element.dataset.target) - this.decimal = element.dataset.decimal === 'true' - this.duration = 2000 - this.startTime = null - - this.init() - } - - init() { - const observer = new IntersectionObserver((entries) => { - entries.forEach(entry => { - if (entry.isIntersecting) { - this.animate() - observer.unobserve(this.element) - } - }) - }, { threshold: 0.5 }) - - observer.observe(this.element) - } - - animate() { - const startValue = 0 - const startTime = performance.now() - - const updateCounter = (currentTime) => { - const elapsedTime = currentTime - startTime - const progress = Math.min(elapsedTime / this.duration, 1) - - // Easing function for smooth animation - const easeOutQuart = 1 - Math.pow(1 - progress, 4) - - let currentValue = startValue + (this.target - startValue) * easeOutQuart - - if (this.decimal && this.target < 10) { - currentValue = currentValue.toFixed(1) - } else { - currentValue = Math.floor(currentValue) - } - - this.element.textContent = currentValue - - if (progress < 1) { - requestAnimationFrame(updateCounter) - } else { - this.element.textContent = this.decimal && this.target < 10 ? this.target.toFixed(1) : this.target - } - } - - requestAnimationFrame(updateCounter) - } -} - -// Initialize all counters -document.addEventListener('DOMContentLoaded', () => { - const counters = document.querySelectorAll('.counter') - counters.forEach(counter => new Counter(counter)) -}) \ No newline at end of file diff --git a/app/javascript/controllers/counter_controller.js b/app/javascript/controllers/counter_controller.js index 139597f..129be1d 100644 --- a/app/javascript/controllers/counter_controller.js +++ b/app/javascript/controllers/counter_controller.js @@ -1,2 +1,61 @@ +import { Controller } from "@hotwired/stimulus" +export default class extends Controller { + static values = { + target: Number, + decimal: Boolean, + duration: { type: Number, default: 2000 } + } + connect() { + this.observer = new IntersectionObserver((entries) => { + entries.forEach(entry => { + if (entry.isIntersecting) { + this.animate() + this.observer.unobserve(this.element) + } + }) + }, { threshold: 0.5 }) + + this.observer.observe(this.element) + } + + disconnect() { + if (this.observer) { + this.observer.disconnect() + } + } + + animate() { + const startValue = 0 + const startTime = performance.now() + + const updateCounter = (currentTime) => { + const elapsedTime = currentTime - startTime + const progress = Math.min(elapsedTime / this.durationValue, 1) + + // Easing function for smooth animation + const easeOutQuart = 1 - Math.pow(1 - progress, 4) + + let currentValue = startValue + (this.targetValue - startValue) * easeOutQuart + + if (this.decimalValue && this.targetValue < 10) { + currentValue = currentValue.toFixed(1) + } else { + currentValue = Math.floor(currentValue) + } + + this.element.textContent = currentValue + + if (progress < 1) { + requestAnimationFrame(updateCounter) + } else { + this.element.textContent = this.decimalValue && this.targetValue < 10 + ? this.targetValue.toFixed(1) + : this.targetValue + } + } + + requestAnimationFrame(updateCounter) + } +} diff --git a/app/javascript/controllers/hello_controller.js b/app/javascript/controllers/hello_controller.js deleted file mode 100644 index 5975c07..0000000 --- a/app/javascript/controllers/hello_controller.js +++ /dev/null @@ -1,7 +0,0 @@ -import { Controller } from "@hotwired/stimulus" - -export default class extends Controller { - connect() { - this.element.textContent = "Hello World!" - } -} diff --git a/app/javascript/controllers/index.js b/app/javascript/controllers/index.js index 934fbb3..c23dca2 100644 --- a/app/javascript/controllers/index.js +++ b/app/javascript/controllers/index.js @@ -4,8 +4,8 @@ import { application } from "./application" -import HelloController from "./hello_controller" import ShadcnTestController from "./shadcn_test_controller" +import CounterController from "./counter_controller" -application.register("hello", HelloController) application.register("shadcn-test", ShadcnTestController) +application.register("counter", CounterController) diff --git a/app/views/pages/home.html.erb b/app/views/pages/home.html.erb index f546bbe..050dd12 100644 --- a/app/views/pages/home.html.erb +++ b/app/views/pages/home.html.erb @@ -37,7 +37,7 @@
- 0 + 0

Événements organisés @@ -53,7 +53,7 @@

- 0+ + 0+

Membres actifs @@ -69,7 +69,7 @@

- 0/5 + 0/5

Note moyenne des soirées @@ -84,28 +84,28 @@

- 0% + 0%

Taux de remplissage

- 0 + 0

Arrondissements

- 0 + 0

Établissements partenaires

- 0% + 0%

Satisfaction client