From cba0bc41b88537c753235512c9357e3aeb81132d Mon Sep 17 00:00:00 2001
From: Dorine Lambinet <dorine.lambinet@assemblee-nationale.fr>
Date: Mon, 10 Mar 2025 10:38:07 +0100
Subject: [PATCH] Copie ancien composant pour les avoir en vue le temps de la
 refacto

---
 .../test_case_selected/PaySlipViewOld.svelte  | 705 ++++++++++++++++++
 .../compare_mode/PaySlipCompareViewOld.svelte | 588 +++++++++++++++
 2 files changed, 1293 insertions(+)
 create mode 100644 src/lib/components/impacts_view/test_cases_view/test_case_selected/PaySlipViewOld.svelte
 create mode 100644 src/lib/components/impacts_view/test_cases_view/test_case_selected/compare_mode/PaySlipCompareViewOld.svelte

diff --git a/src/lib/components/impacts_view/test_cases_view/test_case_selected/PaySlipViewOld.svelte b/src/lib/components/impacts_view/test_cases_view/test_case_selected/PaySlipViewOld.svelte
new file mode 100644
index 000000000..067133a29
--- /dev/null
+++ b/src/lib/components/impacts_view/test_cases_view/test_case_selected/PaySlipViewOld.svelte
@@ -0,0 +1,705 @@
+<script lang="ts">
+  import type { VariableByName } from "@openfisca/json-model"
+
+  import { goto } from "$app/navigation"
+  import OilSpendingBill from "$lib/components/impacts_view/test_cases_view/test_case_selected/OilSpendingBill.svelte"
+  import TestCaseGraph from "$lib/components/impacts_view/test_cases_view/test_case_selected/graph/TestCaseGraph.svelte"
+  import Tooltip from "$lib/components/ui_transverse_components/Tooltip.svelte"
+  import {
+    type VisibleDecomposition,
+    type EvaluationByName,
+    isChildOrDescendant,
+  } from "$lib/decompositions"
+  import { buildVisibleDecompositions } from "$lib/decompositions"
+  import type { DisplayMode } from "$lib/displays"
+  import { entityByKey, personEntityKey } from "$lib/entities"
+  import { trackTestCaseGraph } from "$lib/matomo"
+  import { revaluationName, shared } from "$lib/shared.svelte"
+  import {
+    type ActiveSlider,
+    getSituationVariableValue,
+    setSituationVariableValue,
+    type Situation,
+  } from "$lib/situations"
+  import { newSimulationUrl } from "$lib/urls"
+  import { removeNegativeZero } from "$lib/values"
+  import {
+    oilTypes,
+    type ValuesByCalculationNameByVariableName,
+    type VariableValue,
+  } from "$lib/variables"
+  import LinkedVariables from "$lib/components/impacts_view/test_cases_view/test_case_selected/LinkedVariables.svelte"
+  import { iterToDepth } from "$lib/iterators"
+  import StandardOfLiving from "$lib/components/impacts_view/test_cases_view/test_case_selected/StandardOfLiving.svelte"
+
+  interface Props {
+    displayMode: DisplayMode
+    evaluationByName: EvaluationByName
+    showLoader?: boolean
+    situation: Situation
+    situationIndex: number
+    valuesByCalculationNameByVariableName: ValuesByCalculationNameByVariableName
+    variableSummaryByName: VariableByName
+    year: number
+  }
+
+  let {
+    displayMode,
+    evaluationByName,
+    showLoader = true,
+    situation = $bindable(),
+    situationIndex,
+    valuesByCalculationNameByVariableName,
+    variableSummaryByName,
+    year,
+  }: Props = $props()
+
+  const dateFormatter = new Intl.DateTimeFormat("fr-FR", { dateStyle: "full" })
+    .format
+  const deltaFormatter = (value: number): string =>
+    new Intl.NumberFormat("fr-FR", {
+      currency: "EUR",
+      maximumFractionDigits: 0,
+      minimumFractionDigits: 0,
+      signDisplay: "never",
+      style: "currency",
+    }).format(removeNegativeZero(value))
+  const firstDeltaFormatter = (value: number): string =>
+    new Intl.NumberFormat("fr-FR", {
+      currency: "EUR",
+      maximumFractionDigits: 0,
+      minimumFractionDigits: 0,
+      style: "currency",
+    }).format(removeNegativeZero(value))
+  const personEntity = entityByKey[personEntityKey]
+
+  const oilSpendings = oilTypes.map((name) => ({
+    depenseTtcVariableName: `depense_${name}_ttc`,
+    nombreLitresVariableName: `nombre_litres_${name}`,
+    // prixTtcLitreVariableName: `prix_${name}_hors_remise_ttc_sortie`,
+    prixTtcLitreVariableName: `prix_${name}_ttc`,
+    ticpeVariableName: `${name}_ticpe`,
+    tvaVariableName: `tva_sur_${name}`,
+  }))
+
+  let useRevaluationInsteadOfLaw = $derived(revaluationName !== undefined)
+
+  let firstCalculationName = $derived(
+    useRevaluationInsteadOfLaw ? "revaluation" : "law",
+  )
+
+  let runningCalculationNames = $derived(
+    Object.entries(shared.calculationByName)
+      .filter(([, calculation]) => calculation.running)
+      .map(([calculationName]) => calculationName),
+  )
+
+  let modificationsAmendmentCount = $derived(
+    Object.keys(shared.parametricReform).length,
+  )
+
+  let visibleDecompositions: VisibleDecomposition[] = $state([])
+
+  $effect(() => {
+    visibleDecompositions = buildVisibleDecompositions(
+      shared.decompositionByName,
+      entityByKey,
+      evaluationByName,
+      situation,
+      variableSummaryByName,
+      shared.waterfall,
+      shared.showNulls,
+      useRevaluationInsteadOfLaw,
+      shared.vectorLength,
+      year,
+    )
+  })
+
+  let personSituation = $derived(situation[personEntity.key_plural!])
+
+  function getCorrectSimulationUrl(variableName: string) {
+    const newDisplayMode =
+      displayMode.edit !== undefined
+        ? {
+            ...displayMode,
+            variableName: variableName,
+          }
+        : {
+            ...displayMode,
+            mobileLaw: true,
+            parametersVariableName: variableName,
+          }
+    return newSimulationUrl(newDisplayMode)
+  }
+
+  function getFirstPersonActivity(personSituation) {
+    const populationId = Object.keys(personSituation).sort(
+      (populationId1, populationId2) =>
+        populationId1.localeCompare(populationId2),
+    )[0]
+    return getVariableValue(situation, "activite", populationId)
+  }
+
+  function getVariableValue(
+    situation: Situation,
+    variableName: string,
+    populationId: string,
+  ): VariableValue | undefined {
+    const variable = variableSummaryByName[variableName]
+    if (variable === undefined) {
+      return undefined
+    }
+    return getSituationVariableValue(situation, variable, populationId, year)
+  }
+
+  function removeSituationSlider() {
+    if (shared.savedSituation !== undefined) {
+      situation = shared.savedSituation
+      delete shared.savedSituation
+      if (shared.savedSituationIndex !== undefined) {
+        shared.testCases[shared.savedSituationIndex] = situation
+        delete shared.savedSituationIndex
+      }
+    }
+  }
+
+  function requestAxesCalculation() {
+    // Ensure that situation of previous curve is not merged with the new one.
+    if (
+      shared.savedSituation !== undefined &&
+      shared.savedSituationIndex !== undefined
+    ) {
+      shared.testCases[shared.savedSituationIndex] = shared.savedSituation
+    }
+
+    shared.savedSituation = situation
+    shared.savedSituationIndex = situationIndex
+    situation = structuredClone($state.snapshot(situation))
+    shared.testCases[situationIndex] = situation
+    if (
+      situation.sliders?.length === undefined ||
+      situation.sliders?.length <= 0
+    ) {
+      console.error(
+        "requestAxesCalculation",
+        "Situation sliders list is undefined",
+      )
+      return
+    }
+
+    // Get situation
+    const variable = variableSummaryByName[situation.sliders?.[0].name]
+    const slider = situation.sliders.find(
+      (slider) =>
+        slider.entity === variable.entity && slider.name === variable.name,
+    ) as ActiveSlider | undefined
+
+    if (slider === undefined) {
+      console.error("requestAxesCalculation", "Slider is undefined")
+      return
+    }
+
+    const updatedMin = slider.min
+    const updatedMax = slider.max
+    const updatedStepValue = (updatedMax - updatedMin) / 100 ?? slider.stepValue
+
+    const value = getSituationVariableValue(
+      situation,
+      variable,
+      slider.id,
+      year,
+    ) as number
+
+    const vectorIndex = Math.max(
+      0,
+      Math.min(100, Math.round(value / updatedStepValue)),
+    )
+
+    // Update situation
+    setSituationVariableValue(
+      entityByKey,
+      situation,
+      variable,
+      slider.id,
+      year,
+      Math.round(updatedStepValue * vectorIndex),
+    )
+    situation.slider = {
+      ...slider,
+      min: updatedMin,
+      max: updatedMax,
+      stepValue: updatedStepValue,
+      vectorIndex: vectorIndex,
+    }
+  }
+
+  function zoomIn(index: number) {
+    let visibleDecomposition = visibleDecompositions[index]
+    if (
+      visibleDecomposition === undefined ||
+      visibleDecomposition.visibleChildren === undefined
+    ) {
+      return
+    }
+    let decomposition = visibleDecomposition.decomposition
+    if (!decomposition.open) {
+      shared.decompositionByName[decomposition.name] = {
+        ...decomposition,
+        open: true,
+      }
+      return
+    }
+  }
+
+  function zoomOut(index: number) {
+    let visibleDecomposition = visibleDecompositions[index]
+    if (
+      visibleDecomposition === undefined ||
+      visibleDecomposition.visibleChildren === undefined
+    ) {
+      return
+    }
+    let decomposition = visibleDecomposition.decomposition
+    if (decomposition.open) {
+      shared.decompositionByName[decomposition.name] = {
+        ...decomposition,
+        open: false,
+      }
+      return
+    }
+  }
+</script>
+
+<!--Ce composant se découpe en 3 zones : 
+- ZONE 1 : FEUILLE DE PAIE
+- ZONE 2 : VARIALBES COMPLÉMENTAIRES À LA FEUILLE DE PAIE
+- ZONE 3 : TICKET DE CARBURANT & GRAPHIQUE DES CAS TYPES
+-->
+
+{#if visibleDecompositions.length > 0}
+  {@const firstPersonActivity = getFirstPersonActivity(personSituation)}
+
+  <!--ZONE 1 : FEUILLE DE PAIE -->
+  <!-- Bouton affichage des montants nuls -->
+  <div
+    class="mx-4 mb-3 flex justify-start"
+    id="situation_{situationIndex}_waterfall_showall"
+  >
+    <label class="inline-flex cursor-pointer items-center">
+      <input
+        type="checkbox"
+        value=""
+        class="peer sr-only"
+        bind:checked={shared.showNulls}
+      />
+      <div
+        class="peer relative h-6 w-11 shrink-0 rounded-full bg-gray-400 after:absolute after:start-[2px] after:top-[2px] after:h-5 after:w-5 after:rounded-full after:bg-white after:transition-all after:content-[''] peer-checked:bg-le-bleu peer-checked:after:translate-x-full peer-checked:after:border-white peer-focus:outline-none peer-focus:ring-0"
+      ></div>
+      <span class="ms-3 text-sm font-medium text-gray-900 dark:text-gray-300"
+        >Montrer tous les dispositifs<span
+          class="hidden sm:inline-flex md:hidden lg:inline-flex"
+          >, y compris si leur montant est à 0€</span
+        ></span
+      >
+    </label>
+  </div>
+  <!-- Feuille de paie-->
+  <div class="flex justify-between">
+    <div class="w-3/5 flex-auto">
+      {#each visibleDecompositions as { decomposition, depth, rows, trunk, visibleChildren }, index}
+        <!-- Ligne de la feuille de paie-->
+        <div
+          class="flex min-h-8 items-stretch justify-between border-t border-gray-200 px-4"
+          class:bg-gray-100={trunk && index !== 0}
+          class:border-gray-300={trunk && index !== 0}
+          class:fond={decomposition.name ===
+            displayMode.parametersVariableName ||
+            (displayMode.parametersVariableName &&
+              isChildOrDescendant(
+                shared.decompositionByName,
+                decomposition.name,
+                displayMode.parametersVariableName,
+              ))}
+          class:text-lg={decomposition.name ===
+            displayMode.parametersVariableName}
+          class:items-start={decomposition.name ===
+            displayMode.parametersVariableName}
+        >
+          <!-- Colonne 1 "Nom du dispositif"-->
+          <div class="flex-1 overflow-x-hidden">
+            {#each rows as { calculationName }}
+              {#if calculationName === firstCalculationName}
+                <div class="flex h-full w-full items-center">
+                  <!--Si c'est une variable de type tronc, exemple : Rémunération brute -->
+                  {#if trunk && index !== 0}
+                    <!--Les class permettent que le nom de la variable soit caché avec "..." et rendu visible au survol. Le comportement est différent si la variable est sélectionnée-->
+                    <div
+                      class="flex w-full items-center"
+                      class:whitespace-nowrap={decomposition.name !==
+                        displayMode.parametersVariableName}
+                    >
+                      <!-- Nom de la variable tronc, cliquable -->
+                      <a
+                        class="cursor-pointer overflow-x-hidden text-ellipsis text-gray-500 hover:z-20 hover:overflow-x-visible hover:bg-white hover:bg-opacity-90 hover:pr-1 hover:text-le-gris-dispositif-dark hover:underline"
+                        class:font-bold={decomposition.name ===
+                          displayMode.parametersVariableName}
+                        class:hover:absolute={decomposition.name !==
+                          displayMode.parametersVariableName}
+                        href={getCorrectSimulationUrl(decomposition.name)}
+                        data-sveltekit-noscroll
+                        >{decomposition.short_label ?? decomposition.label}</a
+                      >
+                    </div>
+                  {:else if visibleChildren === undefined}
+                    <!--Si c'est une variable Non-trunk, leaf-variable : La variable n'a pas de variables enfants et elle n'est pas une variable tronc -->
+
+                    <div
+                      class="flex h-full w-full items-center"
+                      class:whitespace-nowrap={decomposition.name !==
+                        displayMode.parametersVariableName}
+                    >
+                      <!--Indentation pour chaque niveau de l'arbre, illustré par une bordure-->
+                      {#each iterToDepth(depth)}
+                        <div
+                          class={`min-h-full border-l-2 bg-white pr-3 ${
+                            decomposition.name !==
+                              displayMode.parametersVariableName &&
+                            !(
+                              displayMode.parametersVariableName &&
+                              isChildOrDescendant(
+                                shared.decompositionByName,
+                                decomposition.name,
+                                displayMode.parametersVariableName,
+                              )
+                            )
+                              ? "border-gray-400"
+                              : "border-black"
+                          }`}
+                        ></div>
+                      {/each}
+                      <!--Si la variable est obsolète, ou que sa date de relecture est inconnue ou trop ancienne, un picto attention est affiché -->
+                      {#if decomposition.obsolete || decomposition.last_value_still_valid_on === undefined || decomposition.last_value_still_valid_on < (new Date().getFullYear() - 2).toString()}
+                        <Tooltip
+                          allowFlip={false}
+                          arrowClass="bg-gray-100"
+                          widthClass="w-80"
+                          initialPlacement="bottom"
+                        >
+                          <iconify-icon
+                            class="mr-0.5 shadow-none {decomposition.obsolete
+                              ? 'text-[#FF4133]'
+                              : 'text-[#FFAC33]'}"
+                            icon="material-symbols:warning-rounded"
+                            width="16"
+                            height="16"
+                          ></iconify-icon>
+                          {#snippet tooltip()}
+                            <div
+                              class="overflow-hidden rounded-lg border border-gray-200 bg-white shadow-2xl"
+                            >
+                              <div
+                                class="border-b border-gray-200 bg-gray-100 px-3 py-2"
+                              >
+                                <h3 class="font-semibold text-gray-900">
+                                  ⚠️ Ce dispositif n'est peut-être pas à jour
+                                </h3>
+                              </div>
+                              <div
+                                class="px-3 py-2 text-sm font-light text-gray-500"
+                              >
+                                Dernière relecture :
+                                {#if decomposition.last_value_still_valid_on === undefined}
+                                  date indéterminée
+                                {:else}{dateFormatter(
+                                    new Date(
+                                      decomposition.last_value_still_valid_on,
+                                    ),
+                                  )}
+                                {/if}
+                                {#if decomposition.obsolete}
+                                  ; Obsolète !{/if}
+                              </div>
+                            </div>
+                          {/snippet}
+                        </Tooltip>
+                      {/if}
+                      <!-- Nom de la variable non-trunk, leaf, cliquable -->
+                      <a
+                        class="cursor-pointer overflow-x-hidden text-ellipsis font-serif hover:z-20 hover:overflow-x-visible hover:bg-white hover:bg-opacity-90 hover:pr-1 hover:text-le-gris-dispositif-dark hover:underline"
+                        class:font-bold={decomposition.name ===
+                          displayMode.parametersVariableName}
+                        class:hover:text-wrap={decomposition.name !==
+                          displayMode.parametersVariableName}
+                        href={getCorrectSimulationUrl(decomposition.name)}
+                        data-sveltekit-noscroll
+                        >{decomposition.short_label ?? decomposition.label}</a
+                      >
+                    </div>
+                  {:else}
+                    <!-- Si c'est une variable Non-trunk, Non-leaf : La variable a des variables enfants et n'est pas une variable tronc | une flèche à droite permet d'ouvrir les variables enfants-->
+
+                    <div
+                      class="flex h-full w-full items-center justify-start"
+                      class:whitespace-nowrap={decomposition.name !==
+                        displayMode.parametersVariableName}
+                    >
+                      <!--Indentation pour chaque niveau de l'arbre, illustré par une bordure-->
+                      {#each iterToDepth(depth)}
+                        <div
+                          class={`min-h-full border-l-2 bg-white pr-3 ${
+                            decomposition.name !==
+                              displayMode.parametersVariableName &&
+                            !(
+                              displayMode.parametersVariableName &&
+                              isChildOrDescendant(
+                                shared.decompositionByName,
+                                decomposition.name,
+                                displayMode.parametersVariableName,
+                              )
+                            )
+                              ? "border-gray-400"
+                              : "border-black"
+                          }`}
+                        ></div>
+                      {/each}
+                      <button
+                        class="cursor-pointer overflow-x-hidden text-ellipsis text-left font-serif hover:z-20 hover:overflow-x-visible hover:bg-white hover:bg-opacity-90 hover:text-le-gris-dispositif-dark hover:underline"
+                        class:hover:text-wrap={decomposition.name !==
+                          displayMode.parametersVariableName}
+                        class:font-bold={decomposition.name ===
+                          displayMode.parametersVariableName}
+                        onclick={() => {
+                          // Non-leaf decomposition node in variable inputs mode => no-link
+                          if (decomposition.open) {
+                            zoomOut(index)
+                          } else {
+                            zoomIn(index)
+                          }
+                          // Leaf decomposition node with parameters in parameters mode => link
+                          if (displayMode.edit === undefined) {
+                            goto(getCorrectSimulationUrl(decomposition.name), {
+                              noScroll: true,
+                            })
+                          }
+                        }}
+                        data-sveltekit-noscroll
+                        >{decomposition.short_label ??
+                          decomposition.label}</button
+                      >
+                      <button
+                        class="text-black"
+                        aria-label={decomposition.open
+                          ? "Ouvrir variables enfants"
+                          : "Fermer"}
+                        onclick={() =>
+                          decomposition.open ? zoomOut(index) : zoomIn(index)}
+                      >
+                        <iconify-icon
+                          class="align-[-0.25rem] text-lg hover:text-le-gris-dispositif"
+                          icon={decomposition.open
+                            ? "ri-arrow-down-s-line"
+                            : "ri-arrow-right-s-line"}
+                        ></iconify-icon>
+                      </button>
+                    </div>
+                  {/if}
+                </div>
+              {/if}
+            {/each}
+          </div>
+
+          <!-- Colonne 2 - Valeur du dispositif-->
+          <div
+            class="flex flex-nowrap pr-1 sm:items-center md:pr-4"
+            class:py-1={!trunk}
+            class:items-end={!trunk}
+          >
+            <div class="flex flex-col justify-end sm:flex-row sm:items-center">
+              {#each rows as { calculationName, deltaAtVectorIndex }}
+                <span
+                  class="h-full pl-1 text-right text-sm"
+                  class:content-center={trunk}
+                  class:content-start={!trunk}
+                >
+                  <!--Loader squelette pendant que la valeur charge -->
+                  {#if showLoader && runningCalculationNames.length > 0}
+                    {#if runningCalculationNames.includes("law") || runningCalculationNames.includes("revaluation")}
+                      <span
+                        class="animate-pulse-2 bg-gray-500 px-1 text-black blur-xs"
+                      >
+                        <span class="text-white blur">value €</span>
+                      </span>
+                    {/if}
+                    {#if runningCalculationNames.includes("bill")}
+                      <span
+                        class="animate-pulse-2 bg-le-rouge-bill px-1 text-black blur-xs"
+                      >
+                        <span class="text-white blur">value €</span>
+                      </span>
+                    {/if}
+                    {#if runningCalculationNames.includes("amendment") && modificationsAmendmentCount > 0}
+                      <span
+                        class="animate-pulse-2 bg-le-jaune px-1 text-black blur-xs"
+                      >
+                        <span class="text-white blur">value €</span>
+                      </span>
+                    {/if}
+                    <!--Valeur du waterfall-->
+                  {:else if trunk && index !== 0}
+                    <span
+                      class=" {calculationName === firstCalculationName
+                        ? rows.find((row) => row.calculationName === 'bill') ===
+                          undefined
+                          ? rows.find(
+                              (row) => row.calculationName === 'amendment',
+                            ) === undefined
+                            ? 'text-gray-500'
+                            : 'text-gray-500 line-through-amendment'
+                          : 'text-gray-500 line-through-bill'
+                        : calculationName === 'bill'
+                          ? rows.find(
+                              (row) => row.calculationName === 'amendment',
+                            ) === undefined
+                            ? 'text-le-rouge-bill'
+                            : 'text-le-rouge-bill line-through-amendment'
+                          : 'bg-le-jaune text-gray-500'}"
+                      class:text-base={decomposition.name !==
+                        displayMode.parametersVariableName}
+                      class:text-2xl={decomposition.name ===
+                        displayMode.parametersVariableName}
+                      class:font-bold={decomposition.name ===
+                        displayMode.parametersVariableName}
+                      ><span
+                        class="content-center pr-1 font-normal text-gray-500"
+                        >=</span
+                      >{firstDeltaFormatter(deltaAtVectorIndex ?? 0)}</span
+                    >
+                  {:else}
+                    <span
+                      class="font-bold {calculationName === firstCalculationName
+                        ? rows.find((row) => row.calculationName === 'bill') ===
+                          undefined
+                          ? rows.find(
+                              (row) => row.calculationName === 'amendment',
+                            ) === undefined
+                            ? ''
+                            : 'line-through-amendment'
+                          : 'line-through-bill'
+                        : calculationName === 'bill'
+                          ? rows.find(
+                              (row) => row.calculationName === 'amendment',
+                            ) === undefined
+                            ? 'text-le-rouge-bill'
+                            : 'text-le-rouge-bill line-through-amendment'
+                          : 'bg-le-jaune'}"
+                      class:opacity-20={decomposition.open}
+                      class:text-base={decomposition.name !==
+                        displayMode.parametersVariableName}
+                      class:text-3xl={decomposition.name ===
+                        displayMode.parametersVariableName}
+                      class:font-semibold={decomposition.name ===
+                        displayMode.parametersVariableName}
+                      >{#if index !== 0}{#if deltaAtVectorIndex < 0}-{:else if deltaAtVectorIndex > 0}+{/if}{/if}
+                      {deltaFormatter(deltaAtVectorIndex ?? 0)}</span
+                    >
+                  {/if}
+                </span>
+              {/each}
+            </div>
+          </div>
+        </div>
+        <!--Affichage des variables liées s'il y en a-->
+        {#if displayMode.parametersVariableName !== undefined && decomposition.name === displayMode.parametersVariableName}
+          <LinkedVariables
+            {displayMode}
+            {evaluationByName}
+            {situationIndex}
+            {variableSummaryByName}
+            {decomposition}
+            {depth}
+            {visibleChildren}
+          />
+        {/if}
+      {/each}
+    </div>
+  </div>
+
+  <!--AJout de la variable niveau de vie-->
+  {#if shared.waterfall.name === "brut_to_disponible"}
+    <StandardOfLiving {situation} {valuesByCalculationNameByVariableName} />
+  {/if}
+
+  <!--ZONE 3.A : TICKET DE CARBURANT-->
+  {#if shared.waterfall.name === "disponible_to_disponible_apres_taxes_carburant"}
+    {#each oilSpendings as { depenseTtcVariableName, nombreLitresVariableName, prixTtcLitreVariableName, ticpeVariableName, tvaVariableName }}
+      <OilSpendingBill
+        {depenseTtcVariableName}
+        {nombreLitresVariableName}
+        {prixTtcLitreVariableName}
+        on:changeTestCaseToEditIndex
+        {situation}
+        {situationIndex}
+        {ticpeVariableName}
+        {tvaVariableName}
+        {valuesByCalculationNameByVariableName}
+        {year}
+      />
+    {/each}
+  {:else}
+    <!--ZONE 3.B : GRAPHIQUE DES CAS TYPES-->
+    {#if firstPersonActivity !== "inactif"}
+      <button
+        class="mt-10 flex w-full items-center gap-2 border-b px-4 py-2 text-start text-neutral-600 transition-all hover:bg-neutral-100 active:bg-neutral-200"
+        onclick={() => {
+          if (situation.slider === undefined) {
+            requestAxesCalculation()
+            trackTestCaseGraph(firstPersonActivity)
+          } else {
+            removeSituationSlider()
+          }
+        }}
+      >
+        <iconify-icon class="text-lg" icon="ri-line-chart-fill"></iconify-icon>
+        <span class="flex-1 font-bold">
+          Voir ce cas type sur un graphique faisant évoluer {#if firstPersonActivity === "actif"}
+            le salaire
+          {:else if firstPersonActivity === "retraite"}
+            la retraite
+          {:else if firstPersonActivity === "chomeur"}
+            le chômage
+          {:else}
+            le revenu
+          {/if}
+          :
+        </span>
+        <iconify-icon
+          class="text-3xl"
+          icon={situation.slider !== undefined
+            ? "ri-arrow-drop-down-line"
+            : "ri-arrow-drop-right-line"}
+        ></iconify-icon>
+      </button>
+      <TestCaseGraph
+        {displayMode}
+        {evaluationByName}
+        evaluationByNameArray={shared.evaluationByNameArray}
+        {situation}
+        {situationIndex}
+        {useRevaluationInsteadOfLaw}
+        {valuesByCalculationNameByVariableName}
+        {variableSummaryByName}
+        vectorLength={shared.vectorLength}
+        waterfall={shared.waterfall}
+        {year}
+      />
+    {/if}
+  {/if}
+{/if}
+
+<style lang="postcss">
+  .fond {
+    background-color: #ffffff;
+    /* Polka dots - Heropatterns.com échelle réduite */
+    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='4' height='4' viewBox='0 0 4 4'%3E%3Cpath fill='%23A0A0A0' fill-opacity='0.4' d='M1 3h1v1H1V3zm2-2h1v1H3V1z'%3E%3C/path%3E%3C/svg%3E");
+  }
+</style>
diff --git a/src/lib/components/impacts_view/test_cases_view/test_case_selected/compare_mode/PaySlipCompareViewOld.svelte b/src/lib/components/impacts_view/test_cases_view/test_case_selected/compare_mode/PaySlipCompareViewOld.svelte
new file mode 100644
index 000000000..9243424b9
--- /dev/null
+++ b/src/lib/components/impacts_view/test_cases_view/test_case_selected/compare_mode/PaySlipCompareViewOld.svelte
@@ -0,0 +1,588 @@
+<script lang="ts">
+  import { preventDefault } from "svelte/legacy"
+
+  import type { VariableByName } from "@openfisca/json-model"
+
+  import { goto } from "$app/navigation"
+  import { page } from "$app/stores"
+  import Tooltip from "$lib/components/ui_transverse_components/Tooltip.svelte"
+  import type {
+    EvaluationByName,
+    VisibleDecompositionForComparison,
+  } from "$lib/decompositions"
+  import { buildVisibleDecompositionsForComparison } from "$lib/decompositions"
+  import type { DisplayMode } from "$lib/displays"
+  import { entityByKey } from "$lib/entities"
+  import { shared } from "$lib/shared.svelte"
+  import type { Situation } from "$lib/situations"
+  import { newSimulationUrl } from "$lib/urls"
+  import { removeNegativeZero } from "$lib/values"
+
+  interface Props {
+    displayMode: DisplayMode
+    evaluationByNameArray: EvaluationByName[]
+    situations: Situation[]
+    situationsToCompareIndex: number[]
+    showLoader?: boolean
+    variableSummaryByName: VariableByName
+    year: number
+  }
+
+  let {
+    displayMode,
+    evaluationByNameArray,
+    situations,
+    situationsToCompareIndex,
+    showLoader = true,
+    variableSummaryByName,
+    year,
+  }: Props = $props()
+
+  const dateFormatter = new Intl.DateTimeFormat("fr-FR", { dateStyle: "full" })
+    .format
+  const deltaFormatter = (value: number): string =>
+    new Intl.NumberFormat("fr-FR", {
+      currency: "EUR",
+      maximumFractionDigits: 0,
+      minimumFractionDigits: 0,
+      signDisplay: "never",
+      style: "currency",
+    }).format(removeNegativeZero(value))
+
+  let useRevaluationInsteadOfLaw = $derived(
+    $page.data.revaluationName !== undefined,
+  )
+
+  let firstCalculationName = $derived(
+    useRevaluationInsteadOfLaw ? "revaluation" : "law",
+  )
+
+  let runningCalculationNames = $derived(
+    Object.entries(shared.calculationByName)
+      .filter(([, calculation]) => calculation.running)
+      .map(([calculationName]) => calculationName),
+  )
+
+  let modificationsAmendmentCount = $derived(
+    Object.keys(shared.parametricReform).length,
+  )
+
+  let visibleDecompositions: VisibleDecompositionForComparison[] = $state([])
+
+  $effect(() => {
+    visibleDecompositions = buildVisibleDecompositionsForComparison(
+      shared.decompositionByName,
+      entityByKey,
+      situationsToCompareIndex.map(
+        (situationIndex) => evaluationByNameArray[situationIndex],
+      ),
+      situationsToCompareIndex.map(
+        (situationIndex) => situations[situationIndex],
+      ),
+      variableSummaryByName,
+      shared.waterfall,
+      shared.showNulls,
+      useRevaluationInsteadOfLaw,
+      shared.vectorLength,
+      year,
+    )
+  })
+
+  function* iterToDepth(depth: number): Generator<number, void, unknown> {
+    for (let i = 0; i < depth; i++) {
+      yield i
+    }
+  }
+
+  function zoomIn(index: number) {
+    let visibleDecomposition = visibleDecompositions[index]
+    if (
+      visibleDecomposition === undefined ||
+      visibleDecomposition.visibleChildren === undefined
+    ) {
+      return
+    }
+    let decomposition = visibleDecomposition.decomposition
+    if (!decomposition.open) {
+      shared.decompositionByName[decomposition.name] = {
+        ...decomposition,
+        open: true,
+      }
+      return
+    }
+  }
+
+  function zoomOut(index: number) {
+    let visibleDecomposition = visibleDecompositions[index]
+    if (
+      visibleDecomposition === undefined ||
+      visibleDecomposition.visibleChildren === undefined
+    ) {
+      return
+    }
+    let decomposition = visibleDecomposition.decomposition
+    if (decomposition.open) {
+      shared.decompositionByName[decomposition.name] = {
+        ...decomposition,
+        open: false,
+      }
+      return
+    }
+  }
+</script>
+
+{#if visibleDecompositions.length > 0}
+  <div>
+    <div class="h-5 bg-gradient-to-b from-gray-100 to-transparent" />
+    <!--Montants-nuls-->
+    <div class="mx-1 mb-3 flex justify-start">
+      <label class="inline-flex cursor-pointer items-center">
+        <input
+          type="checkbox"
+          value=""
+          class="peer sr-only"
+          bind:checked={shared.showNulls}
+        />
+        <div
+          class="peer relative h-6 w-11 shrink-0 rounded-full bg-gray-400 after:absolute after:start-[2px] after:top-[2px] after:h-5 after:w-5 after:rounded-full after:bg-white after:transition-all after:content-[''] peer-checked:bg-le-bleu peer-checked:after:translate-x-full peer-checked:after:border-white peer-focus:outline-none peer-focus:ring-0"
+        ></div>
+        <span class="ms-3 text-sm font-medium text-gray-900 dark:text-gray-300"
+          >Montrer tous les dispositifs, y compris si leur montant est à 0€.</span
+        >
+      </label>
+    </div>
+  </div>
+  <!-- Labels and compared amounts of decompositions -->
+  <div>
+    {#each visibleDecompositions as { decomposition, depth, rows, trunk, visibleChildren }, index}
+      <!-- Decomposition label -->
+      <div class="flex h-7 items-center whitespace-nowrap">
+        {#if trunk}
+          <div
+            class="ml-2 mt-2 w-full overflow-x-hidden text-ellipsis border-gray-300 text-left text-base text-gray-500 hover:z-20 hover:overflow-x-visible"
+            class:border-t={index !== 0}
+          >
+            {#if displayMode.edit !== undefined}
+              <!-- Trunk decomposition node, in variable inputs mode => link -->
+              <a
+                class="cursor-pointer text-base hover:underline"
+                href={newSimulationUrl({
+                  ...displayMode,
+                  variableName: decomposition.name,
+                })}
+                data-sveltekit-noscroll
+                >{decomposition.short_label ?? decomposition.label}</a
+              >
+            {:else}
+              <!-- Trunk decomposition node with parameters, in parameters mode => link -->
+              <a
+                class="cursor-pointer text-base hover:underline"
+                href={newSimulationUrl({
+                  ...displayMode,
+                  mobileLaw: true,
+                  parametersVariableName: decomposition.name,
+                })}
+                data-sveltekit-noscroll
+                >{decomposition.short_label ?? decomposition.label}</a
+              >
+            {/if}
+          </div>
+        {:else}
+          {#each [...iterToDepth(depth)] as _level}
+            <div class="ml-2 h-full border-l border-le-gris-dispositif">
+              &nbsp;
+            </div>
+          {/each}
+          {#if visibleChildren === undefined}
+            <!-- Leaf node (except the first one, that belongs to trunk) -->
+            <div class="ml-4">
+              {#if decomposition.obsolete || decomposition.last_value_still_valid_on === undefined || decomposition.last_value_still_valid_on < (new Date().getFullYear() - 2).toString()}
+                <Tooltip
+                  allowFlip={false}
+                  arrowClass="bg-gray-100"
+                  widthClass="w-80"
+                  initialPlacement="bottom"
+                >
+                  <iconify-icon
+                    class="mr-1 shadow-none {decomposition.obsolete
+                      ? 'text-[#FF4133]'
+                      : 'text-[#FFAC33]'}"
+                    icon="material-symbols:warning-rounded"
+                    width="16"
+                    height="16"
+                  ></iconify-icon>
+                  {#snippet tooltip()}
+                    <div
+                      class="overflow-hidden rounded-lg border border-gray-200 bg-white shadow-2xl"
+                    >
+                      <div
+                        class="border-b border-gray-200 bg-gray-100 px-3 py-2"
+                      >
+                        <h3 class="font-semibold text-gray-900">
+                          ⚠️ Ce dispositif n'est peut-être pas à jour
+                        </h3>
+                      </div>
+                      <div class="px-3 py-2 text-sm font-light text-gray-500">
+                        Dernière relecture :
+                        {#if decomposition.last_value_still_valid_on === undefined}
+                          date indéterminée
+                        {:else}{dateFormatter(
+                            new Date(decomposition.last_value_still_valid_on),
+                          )}
+                        {/if}
+                        {#if decomposition.obsolete}
+                          ; Obsolète !{/if}
+                      </div>
+                    </div>
+                  {/snippet}
+                </Tooltip>
+              {/if}
+            </div>
+
+            {#if displayMode.edit !== undefined}
+              <!-- Leaf decomposition node in variable inputs mode => link -->
+              <a
+                class="cursor-pointer overflow-x-hidden text-ellipsis font-serif text-base hover:z-20 hover:overflow-x-visible hover:bg-white hover:text-le-gris-dispositif hover:underline"
+                href={newSimulationUrl({
+                  ...displayMode,
+                  variableName: decomposition.name,
+                })}
+                data-sveltekit-noscroll
+                >{decomposition.short_label ?? decomposition.label}</a
+              >
+            {:else}
+              <!-- Leaf decomposition node with parameters in parameters mode => link -->
+              <a
+                class="cursor-pointer overflow-x-hidden text-ellipsis font-serif text-base hover:z-20 hover:overflow-x-visible hover:bg-white hover:text-le-gris-dispositif hover:underline"
+                href={newSimulationUrl({
+                  ...displayMode,
+                  mobileLaw: true,
+                  parametersVariableName: decomposition.name,
+                })}
+                data-sveltekit-noscroll
+                >{decomposition.short_label ?? decomposition.label}</a
+              >
+            {/if}
+          {:else}
+            <!-- Non-trunk, non-leaf variablev-->
+            {#if decomposition.open}
+              <button class="p-0 text-black" onclick={() => zoomOut(index)}>
+                <iconify-icon
+                  class="align-[-0.2rem] text-lg"
+                  icon="ri-arrow-up-s-line"
+                ></iconify-icon>
+              </button>
+            {:else}
+              <button class="p-0 text-black" onclick={() => zoomIn(index)}>
+                <iconify-icon
+                  class="align-[-0.2rem] text-lg"
+                  icon="ri-arrow-right-s-line"
+                ></iconify-icon>
+              </button>
+            {/if}
+
+            {#if displayMode.edit !== undefined}
+              <!-- Non-lead decomposition node in variable inputs mode => no-link -->
+              <button
+                class="cursor-pointer overflow-x-hidden text-ellipsis font-serif text-base text-black hover:z-20 hover:overflow-x-visible hover:bg-white hover:text-black hover:underline"
+                onclick={() => {
+                  if (decomposition.open) {
+                    zoomOut(index)
+                  } else {
+                    zoomIn(index)
+                  }
+                }}
+              >
+                {decomposition.short_label ?? decomposition.label}
+              </button>
+            {:else}
+              <!-- Leaf decomposition node with parameters in parameters mode => link -->
+              <a
+                class="cursor-pointer overflow-x-hidden text-ellipsis font-serif text-base hover:z-20 hover:overflow-x-visible hover:bg-white hover:text-le-gris-dispositif hover:underline"
+                href={newSimulationUrl({
+                  ...displayMode,
+                  parametersVariableName: decomposition.name,
+                })}
+                onclick={preventDefault(() => {
+                  if (decomposition.open) {
+                    zoomOut(index)
+                  } else {
+                    zoomIn(index)
+                  }
+                  goto(
+                    newSimulationUrl({
+                      ...displayMode,
+                      parametersVariableName: decomposition.name,
+                    }),
+                    { noScroll: true },
+                  )
+                })}
+                data-sveltekit-noscroll
+                >{decomposition.short_label ?? decomposition.label}</a
+              >
+            {/if}
+          {/if}
+        {/if}
+      </div>
+
+      {#each rows as { calculationName, deltaAtVectorIndexArray }}
+        <!-- Decomposition compared amounts -->
+        {#if !decomposition.open || trunk || index === 0}
+          <div class="relative flex items-center whitespace-nowrap">
+            {#if !decomposition.open && !trunk}
+              <div class="absolute">
+                {#each iterToDepth(depth)}
+                  <div class="ml-2 h-full border-l border-le-gris-dispositif">
+                    &nbsp;
+                  </div>
+                {/each}
+              </div>
+            {/if}
+            <div
+              class="justify-center {decomposition.open &&
+              trunk &&
+              visibleChildren.length > 1 &&
+              calculationName === firstCalculationName
+                ? ''
+                : ' border-none'} {calculationName === firstCalculationName
+                ? ''
+                : '-mt-1 mb-1'} flex w-full text-sm"
+            >
+              {#if decomposition.open || index === 0}
+                <!---Composant loader pour les valeurs intermédiaires-->
+                {#if showLoader && runningCalculationNames.length > 0}
+                  {#if runningCalculationNames.includes("law") || runningCalculationNames.includes("revaluation")}<span
+                      class="mx-1 animate-pulse-2 bg-gray-500 px-1 text-black blur-xs"
+                    >
+                      <span class="text-white blur">value €</span>
+                    </span>
+                  {/if}
+                  {#if runningCalculationNames.includes("bill")}
+                    <span
+                      class="mx-1 animate-pulse-2 bg-le-rouge-bill px-1 text-black blur-xs"
+                    >
+                      <span class="text-white blur">value €</span>
+                    </span>
+                  {/if}
+                  {#if runningCalculationNames.includes("amendment") && modificationsAmendmentCount > 0}
+                    <span
+                      class="mx-1 animate-pulse-2 bg-le-jaune px-1 text-black blur-xs"
+                    >
+                      <span class="text-white blur">value €</span>
+                    </span>
+                  {/if}
+                  <!--Valeurs du waterfall des montants intermédiaires -->
+                {:else if trunk || index === 0}
+                  {#if deltaAtVectorIndexArray[0] === deltaAtVectorIndexArray[1]}
+                    {#if decomposition.open && trunk}
+                      <span class="mx-2 text-gray-500">=</span>
+                    {/if}
+                    <span
+                      class="text-sm {calculationName === firstCalculationName
+                        ? rows.find((row) => row.calculationName === 'bill') ===
+                          undefined
+                          ? rows.find(
+                              (row) => row.calculationName === 'amendment',
+                            ) === undefined
+                            ? 'text-gray-500'
+                            : 'text-gray-500 line-through-amendment'
+                          : 'text-gray-500 line-through-bill'
+                        : calculationName === 'bill'
+                          ? rows.find(
+                              (row) => row.calculationName === 'amendment',
+                            ) === undefined
+                            ? 'text-le-rouge-bill'
+                            : 'text-le-rouge-bill line-through-amendment'
+                          : 'bg-le-jaune'}"
+                      >{deltaFormatter(deltaAtVectorIndexArray[0] ?? 0)}</span
+                    >
+                  {:else}
+                    <div class="flex w-full justify-center">
+                      <div class="mx-4 w-1/2">
+                        {#if decomposition.open && trunk}
+                          <span class="mx-2 text-gray-500">=</span>
+                        {/if}
+                        <span
+                          class="text-right text-sm {calculationName ===
+                          firstCalculationName
+                            ? rows.find(
+                                (row) => row.calculationName === 'bill',
+                              ) === undefined
+                              ? rows.find(
+                                  (row) => row.calculationName === 'amendment',
+                                ) === undefined
+                                ? 'text-gray-500'
+                                : 'text-gray-500 line-through-amendment'
+                              : 'text-gray-500 line-through-bill'
+                            : calculationName === 'bill'
+                              ? rows.find(
+                                  (row) => row.calculationName === 'amendment',
+                                ) === undefined
+                                ? 'text-le-rouge-bill'
+                                : 'text-le-rouge-bill line-through-amendment'
+                              : 'bg-le-jaune'}"
+                          >{deltaFormatter(
+                            deltaAtVectorIndexArray[0] ?? 0,
+                          )}</span
+                        >
+                      </div>
+                      <div class="mx-4 w-1/2">
+                        {#if decomposition.open && trunk}
+                          <span class="mx-2 text-gray-500">=</span>
+                        {/if}
+                        <span
+                          class="text-left text-sm {calculationName ===
+                          firstCalculationName
+                            ? rows.find(
+                                (row) => row.calculationName === 'bill',
+                              ) === undefined
+                              ? rows.find(
+                                  (row) => row.calculationName === 'amendment',
+                                ) === undefined
+                                ? 'text-gray-500'
+                                : 'text-gray-500 line-through-amendment'
+                              : 'text-gray-500 line-through-bill'
+                            : calculationName === 'bill'
+                              ? rows.find(
+                                  (row) => row.calculationName === 'amendment',
+                                ) === undefined
+                                ? 'text-le-rouge-bill'
+                                : 'text-le-rouge-bill line-through-amendment'
+                              : 'bg-le-jaune'}"
+                          >{deltaFormatter(
+                            deltaAtVectorIndexArray[1] ?? 0,
+                          )}</span
+                        >
+                      </div>
+                    </div>
+                  {/if}
+                {/if}
+                <!--Montant des dispositifs-->
+              {:else if deltaAtVectorIndexArray[0] === deltaAtVectorIndexArray[1]}
+                <!---Composant loader pour la valeur suivante-->
+                {#if showLoader && runningCalculationNames.length > 0}
+                  {#if runningCalculationNames.includes("law") || runningCalculationNames.includes("revaluation")}<span
+                      class="mx-1 animate-pulse-2 bg-gray-500 px-1 text-black blur-xs"
+                    >
+                      <span class="text-white blur">value €</span>
+                    </span>
+                  {/if}
+                  {#if runningCalculationNames.includes("bill")}
+                    <span
+                      class="mx-1 animate-pulse-2 bg-le-rouge-bill px-1 text-black blur-xs"
+                    >
+                      <span class="text-white blur">value €</span>
+                    </span>
+                  {/if}
+                  {#if runningCalculationNames.includes("amendment") && modificationsAmendmentCount > 0}
+                    <span
+                      class="mx-1 animate-pulse-2 bg-le-jaune px-1 text-black blur-xs"
+                    >
+                      <span class="text-white blur">value €</span>
+                    </span>
+                  {/if}
+                  <!--Valeur-->
+                {:else}
+                  <span
+                    class="text-base font-bold {calculationName ===
+                    firstCalculationName
+                      ? rows.find((row) => row.calculationName === 'bill') ===
+                        undefined
+                        ? rows.find(
+                            (row) => row.calculationName === 'amendment',
+                          ) === undefined
+                          ? ''
+                          : 'line-through-amendment'
+                        : 'line-through-bill'
+                      : calculationName === 'bill'
+                        ? rows.find(
+                            (row) => row.calculationName === 'amendment',
+                          ) === undefined
+                          ? 'text-le-rouge-bill'
+                          : 'text-le-rouge-bill line-through-amendment'
+                        : 'bg-le-jaune'}"
+                    >{deltaFormatter(deltaAtVectorIndexArray[0] ?? 0)}</span
+                  >
+                {/if}
+              {:else}
+                <!---Composant loader pour la valeur suivante-->
+                {#if showLoader && runningCalculationNames.length > 0}
+                  {#if runningCalculationNames.includes("law") || runningCalculationNames.includes("revaluation")}<span
+                      class="mx-1 animate-pulse-2 bg-gray-500 px-1 text-black blur-xs"
+                    >
+                      <span class="text-white blur">value €</span>
+                    </span>
+                  {/if}
+                  {#if runningCalculationNames.includes("bill")}
+                    <span
+                      class="mx-1 animate-pulse-2 bg-le-rouge-bill px-1 text-black blur-xs"
+                    >
+                      <span class="text-white blur">value €</span>
+                    </span>
+                  {/if}
+                  {#if runningCalculationNames.includes("amendment") && modificationsAmendmentCount > 0}
+                    <span
+                      class="mx-1 animate-pulse-2 bg-le-jaune px-1 text-black blur-xs"
+                    >
+                      <span class="text-white blur">value €</span>
+                    </span>
+                  {/if}
+                  <!--Valeur dispositifs-->
+                {:else}
+                  <div class="flex w-full justify-center">
+                    <div class="mx-4 w-1/2">
+                      <span
+                        class="text-base font-bold {calculationName ===
+                        firstCalculationName
+                          ? rows.find(
+                              (row) => row.calculationName === 'bill',
+                            ) === undefined
+                            ? rows.find(
+                                (row) => row.calculationName === 'amendment',
+                              ) === undefined
+                              ? ''
+                              : 'line-through-amendment'
+                            : 'line-through-bill'
+                          : calculationName === 'bill'
+                            ? rows.find(
+                                (row) => row.calculationName === 'amendment',
+                              ) === undefined
+                              ? 'text-le-rouge-bill'
+                              : 'text-le-rouge-bill line-through-amendment'
+                            : 'bg-le-jaune'}"
+                        >{deltaFormatter(deltaAtVectorIndexArray[0] ?? 0)}</span
+                      >
+                    </div>
+                    <div class="mx-4 w-1/2">
+                      <span
+                        class="text-base font-bold {calculationName ===
+                        firstCalculationName
+                          ? rows.find(
+                              (row) => row.calculationName === 'bill',
+                            ) === undefined
+                            ? rows.find(
+                                (row) => row.calculationName === 'amendment',
+                              ) === undefined
+                              ? ''
+                              : 'line-through-amendment'
+                            : 'line-through-bill'
+                          : calculationName === 'bill'
+                            ? rows.find(
+                                (row) => row.calculationName === 'amendment',
+                              ) === undefined
+                              ? 'text-le-rouge-bill'
+                              : 'text-le-rouge-bill line-through-amendment'
+                            : 'bg-le-jaune'}"
+                        >{deltaFormatter(deltaAtVectorIndexArray[1] ?? 0)}</span
+                      >
+                    </div>
+                  </div>
+                {/if}
+              {/if}
+            </div>
+          </div>
+        {/if}
+      {/each}
+    {/each}
+  </div>
+{/if}
-- 
GitLab