Publish Oksana week 15 plan v7
Sekta Engineer committed 2026-09-13 15:38:58 +0300

Analyzing diff...

plans/oksana/weeks-15/index.html+55 −23
index 37cf1c1..0ba1217 100644
--- a/plans/oksana/weeks-15/index.html
+++ b/plans/oksana/weeks-15/index.html
@@ -183,7 +183,7 @@
       .session {
         position: relative;
         margin: 10px 0;
-        padding: 14px 48px 14px 14px;
+        padding: 14px;
         border: 1px solid var(--line);
         border-radius: 16px;
         background: #fff;
@@ -198,19 +198,28 @@
         color: var(--muted);
         margin-top: 4px;
       }
-      .session input {
-        position: absolute;
-        right: 15px;
-        top: 17px;
+      .workout-completion {
+        display: flex;
+        align-items: center;
+        gap: 10px;
+        margin: 14px 0 4px;
+        padding: 13px;
+        border: 1px solid #b9d5c7;
+        border-radius: 15px;
+        background: #edf7f1;
+        font-weight: 800;
+      }
+      .workout-completion input {
         width: 22px;
         height: 22px;
         accent-color: var(--green);
       }
-      .session.done {
-        opacity: 0.62;
-      }
-      .session.done a {
-        text-decoration: line-through;
+      .workout-guidance {
+        margin: 14px 0 4px;
+        padding: 13px 15px;
+        border-radius: 15px;
+        background: var(--peach2);
+        color: #654d40;
       }
       .note {
         width: 100%;
@@ -414,14 +423,14 @@
       </header>
       <div class="progress">
         <div class="progress-row">
-          <span>Прогресс недели</span><span id="count">0 из 54</span>
+          <span>Прогресс недели</span><span id="count">0 из 46</span>
         </div>
         <div
           class="track"
           role="progressbar"
           aria-label="Прогресс недели"
           aria-valuemin="0"
-          aria-valuemax="54"
+          aria-valuemax="46"
           aria-valuenow="0"
         >
           <div class="fill" id="fill"></div>
@@ -439,6 +448,11 @@
           Листайте дни стрелками или свайпом. Под тренировками можно отметить
           ежедневный МТД и утреннюю часовую прогулку.
         </p>
+        <p class="workout-guidance">
+          Учитывая восстановление после болезни, выполняйте одну тренировку
+          блока — любую, которая откликнется по времени, нагрузке и
+          самочувствию.
+        </p>
         <div class="days-nav">
           <button class="navbtn" id="prev" aria-label="Предыдущий день">
             ←
@@ -625,7 +639,15 @@
       } catch (e) {}
       const save = () => localStorage.setItem(STORE, JSON.stringify(state));
       const key = (d, i) => `d${d}-s${i}`;
+      const workoutKey = (d) => `d${d}-workout`;
       const hkey = (d, i) => `d${d}-h${i}`;
+      days.forEach((d, di) => {
+        const newKey = workoutKey(di);
+        if (!(newKey in state.checks) && d.items.some((x, i) => state.checks[key(di, i)])) {
+          state.checks[newKey] = true;
+        }
+      });
+      save();
       function mins(meta) {
         const m = meta.match(/(\d{2}):(\d{2})/);
         return m ? +m[1] + +m[2] / 60 : 0;
@@ -653,20 +675,23 @@
         let items = d.items
           .map(
             (x, i) =>
-              `<div class="session ${state.checks[key(state.day, i)] ? "done" : ""}"><a href="${x[1]}" target="_blank" rel="noopener">${x[0]}</a><small>${x[2]}</small><input type="checkbox" data-check="${key(state.day, i)}" ${state.checks[key(state.day, i)] ? "checked" : ""} aria-label="Отметить ${x[0]}"></div>`,
+              `<div class="session" data-role="workout-option" data-item-id="d${state.day}-option-${i}"><a href="${x[1]}" target="_blank" rel="noopener">${x[0]}</a><small>${x[2]}</small></div>`,
           )
           .join("");
+        const completion = d.items.length
+          ? `<label class="workout-completion" data-role="completion"><input type="checkbox" data-check="${workoutKey(state.day)}" ${state.checks[workoutKey(state.day)] ? "checked" : ""}> Выполнила одну тренировку блока</label>`
+          : "";
         let habits =
           state.day < 6
             ? daily
                 .map(
                   (x, i) =>
-                    `<label class="habit"><input type="checkbox" data-check="${hkey(state.day, i)}" ${state.checks[hkey(state.day, i)] ? "checked" : ""}> ${x[1] ? `<a href="${x[1]}" target="_blank" rel="noopener">${x[0]}</a>` : x[0]}</label>`,
+                    `<label class="habit" data-role="daily-support" data-item-id="d${state.day}-support-${i}"><input type="checkbox" data-check="${hkey(state.day, i)}" ${state.checks[hkey(state.day, i)] ? "checked" : ""}> ${x[1] ? `<a href="${x[1]}" target="_blank" rel="noopener">${x[0]}</a>` : x[0]}</label>`,
                 )
                 .join("")
             : "";
         document.getElementById("day").innerHTML =
-          `<article class="day-card"><div class="day-head"><div><h2>${d.name}</h2><div>${d.theme}</div></div>${d.items.length ? `<span class="total">${fmt(total(d))}</span>` : ""}</div>${items}${habits}<textarea class="note" data-note="${state.day}" placeholder="Комментарий к дню">${state.notes[state.day] || ""}</textarea></article>`;
+          `<article class="day-card" data-day-card="${state.day}"><div class="day-head"><div><h2>${d.name}</h2><div>${d.theme}</div></div>${d.items.length ? `<span class="total">выберите 1</span>` : ""}</div>${items}${completion}${habits}<textarea class="note" data-note="${state.day}" placeholder="Комментарий к дню">${state.notes[state.day] || ""}</textarea></article>`;
         bind();
         progress();
       }
@@ -693,11 +718,20 @@
         };
       }
       function progress() {
-        const planned = 14 + 12 + 28;
+        const workoutKeys = days
+          .map((d, di) => (d.items.length ? workoutKey(di) : null))
+          .filter(Boolean);
+        const supportKeys = days.flatMap((d, di) =>
+          di < 6 ? daily.map((x, i) => hkey(di, i)) : [],
+        );
+        const mealKeys = days.flatMap((d, di) =>
+          foodItems.map(([id]) => foodKey(di, id)),
+        );
+        const planned = workoutKeys.length + supportKeys.length + mealKeys.length;
         const done =
-          Object.values(state.checks).filter(Boolean).length +
-          Object.entries(state.food).filter(([k, v]) => k.includes("-") && v)
-            .length;
+          workoutKeys.filter((k) => state.checks[k]).length +
+          supportKeys.filter((k) => state.checks[k]).length +
+          mealKeys.filter((k) => state.food[k]).length;
         document.getElementById("count").textContent = `${done} из ${planned}`;
         document.getElementById("fill").style.width =
           `${Math.min((done / planned) * 100, 100)}%`;
@@ -757,13 +791,11 @@
       function report() {
         let out = ["Итоги 15-й недели Оксаны", ""];
         days.slice(0, 6).forEach((d, di) => {
-          const done = d.items
-            .filter((x, i) => state.checks[key(di, i)])
-            .map((x) => x[0]);
+          const workout = state.checks[workoutKey(di)] ? "выполнена" : "нет отметки";
           const mt = state.checks[hkey(di, 0)] ? "да" : "нет";
           const walk = state.checks[hkey(di, 1)] ? "да" : "нет";
           out.push(
-            `${d.name}: тренировки — ${done.length ? done.join(", ") : "нет отметок"}; МТД — ${mt}; прогулка — ${walk}.`,
+            `${d.name}: одна тренировка блока — ${workout}; МТД — ${mt}; прогулка — ${walk}.`,
           );
           if (state.notes[di]) out.push(`Комментарий: ${state.notes[di]}`);
         });