Orogel - Un progetto di manutenzione e sviluppo

Un progetto che mi ha visto intervenire su tecnologia Strapi + Vue.js per sviluppare nuove funzionalità

Vue.js
Strapi
Orogel - Un progetto di manutenzione e sviluppo

Introduzione

In questo progetto mi sono interfacciato per la prima volta con il framework Vue.js, dopo anni di esperienza con Next.js e React. Il passaggio ha richiesto un adattamento significativo: dalla gestione dello stato con hooks a Composition API, dalla sintassi JSX ai template Vue, fino alle differenze nel ciclo di vita dei componenti e nella reattività. Nonostante le sfide iniziali, l'intelligenza artificiale si è rivelata un alleato prezioso in questo processo di apprendimento, aiutandomi a comprendere rapidamente le best practices di Vue.js, a tradurre pattern React in equivalenti Vue, e a risolvere problematiche specifiche del framework in modo efficiente. Questa esperienza ha ampliato notevolmente il mio stack tecnologico e la mia capacità di adattamento a nuovi ecosistemi di sviluppo.

Le sfide principali

Ho ereditato una infrastruttura carente di documentazione sia sul suo funzionamento sia sui processi di deploy. Ho dovuto recuperare tutte le informazioni circa la riproduzione dell’ambiente locale che usava versioni di node più vecchie e separate tra /api e /frontend, sia sulla gestione del filestorage.

  • Aggiunta nuova documentazione a supporto di futuri dev
  • Verificato lo stato dell'arte (versioni e gestione degli ambienti)
  • Verificato lo stato di git e l'approccio
  • Definita la strategia da usare

Ho valutato di non ereditare il git flow precedente che prevedeva per ogni feature (anche mini) un branch dedicato in quanto lavoravo da solo e avevo bisogna di rapidtà per cui a meno di grandi modifiche procedevo con commit singoli, ben strutturati, da pushare in staging per le verifiche e poi in produzione.

Prima richiesta

La prima richiesta mi ha visto coinvolto in un problem full-stack che per il cliente risultava come una operazione solo visiva: si voleva aggiungere un moltiplicatore di dosi nella pagina delle ricette.

I dati su strapi erano strutturati in modo testuale e non separati in modo organizzato es. “100 grammi di Pasta” è un blocco di testo unico.

Per esigenze di progetto non si poteva optare a una ristrutturazione dei dati a db in quanto non c’era tempo né la volontà degli editor di adottare questo cambiamento, pertanto, ho deciso di riprodurre una soluzione lato client efficacie.

Il moltiplicatore di ricette è implementato nel componente RecipeIngredients.vue e permette agli utenti di scalare automaticamente le quantità degli ingredienti in base al numero di porzioni desiderate.

L'interfaccia mostra pulsanti +/- per incrementare/decrementare di 2 porzioni (range da 1 a 12). Il calcolo avviene in tempo reale: estrae i numeri dal testo degli ingredienti usando regex, calcola il rapporto tra moltiplicatore attuale e porzioni iniziali, moltiplica il valore originale e mantiene i decimali se presenti nell'originale.

jsx
1<div class="flex items-center gap-2 justify-start">
2 <button
3 :disabled="multiplier <= 1"
4 class="w-10 h-10 flex items-center justify-center rounded-full border border-green-200 text-green-200 disabled:opacity-40"
5 @click="decrement"
6 >
7 <svg-icon name="minus" class="w-5 h-5" />
8 </button>
9 <div class="flex items-center justify-center">
10 <svg-icon name="icona-porzioni" class="w-9 h-9 text-green-200" />
11 </div>
12 <span class="text-22 font-bold text-green-200">x {{ multiplier }}</span>
13 <button
14 :disabled="multiplier >= 12"
15 class="w-10 h-10 flex items-center justify-center rounded-full border border-green-200 text-green-200 disabled:opacity-40"
16 @click="increment"
17 >
18 <svg-icon name="add" class="w-5 h-5" />
19 </button>
20</div>

La logica di calcolo utilizza una computed property che mappa ogni ingrediente:

javascript
1computedIngredients() {
2 return this.ingredients.map((ingredient) => {
3 let text = ingredient.text
4 const match = text.match(/(\d+[.,]?\d*)/)
5 if (match) {
6 const original = match[0].replace(",", ".")
7 const value = parseFloat(original)
8 if (!isNaN(value)) {
9 const defaultPortionsValue = this.parsePortions(this.defaultPortions)
10 const ratio = this.multiplier / defaultPortionsValue
11 const newValue = value * ratio
12 const formatted = original.includes(".") || original.includes(",")
13 ? newValue.toFixed(2).replace(".", ",")
14 : Math.round(newValue)
15 text = text.replace(match[0], formatted)
16 }
17 }
18 return { text, link: this.getIngredientLink(ingredient), productImage: this.getProductImage(ingredient) }
19 })
20}

Il parsing delle porzioni gestisce sia stringhe che numeri:

javascript
1parsePortions(portions) {
2 if (typeof portions === "number") return portions
3 if (typeof portions === "string") {
4 const match = portions.match(/\d+/)
5 return match ? parseInt(match[0]) : 1
6 }
7 return 1
8}

Esempio pratico: una ricetta per 4 porzioni con "500g di pomodori", portata a 8 porzioni (ratio = 8/4 = 2), diventa "1000g di pomodori".

Screenshot del componente in questione con dettaglio sul moltiplicatore implementato

Altri interventi, componenti e funzionalità varie

Mi sono occupato poi di vari restlying di componenti e/o implementazioni di nuove funzionalità tra cui:

Slider per hero in homepage

Uno slider per gestire dinamicamente le campagne con autoscroll e design minimal


Nuovo attributo per ricette in trend

Inserimento di un nuovo attributo in Strapi per determinare se la ricetta inserita è una ricetta in trend


Video box intuitivo per le ricette in trend

Modifica del componente immagine per gestire i video delle ricette in trend. Su Strapi quando una ricetta è in trend/influncer si può caricare un file video che viene inserito nella pagina. L’immagine principale diventa copertina/poster per il video e quest’ultimo rimane riproducibile tramite i controlli dedicati


Nuovo carosello con animazioni dedicate

Il carosello aveva come obiettivo quello di mostrare il pacco e lo sfondo usato nel contenuto in modo integrato. Puoi provarlo qui


Conclusione

Ritengo, con questo progetto, di aver aumentato considerevolmente le mie competenze con l’uso di Strapi e con l’uso di Vue. Ho inoltrate esteso la mia conoscenza di Gitlab che avevo usato solo a scopo amatoriale riuscendo a gestire dignitosamente l’orchestrazione dei repository e dei processi CI/CD dedicati

Grazie per aver visionato questo progetto