const STORAGE_KEY = 'gym_tracker_v6'; // Палитра из 16 контрастных цветов для клиентов export const CLIENT_COLORS = [ '#bb86fc', // фиолетовый (дефолтный для личного режима) '#03dac6', // бирюзовый '#fbbc04', // жёлтый '#cf6679', // розовый '#64b5f6', // голубой '#81c784', // зелёный '#ffb74d', // оранжевый '#ba68c8', // светло-фиолетовый '#4dd0e1', // циан '#e57373', // красный '#aed581', // салатовый '#ffd54f', // янтарный '#9575cd', // пурпурный '#4db6ac', // тиловый '#f06292', // малиновый '#7986cb', // индиго ]; export const DEFAULT_COLOR = CLIENT_COLORS[0]; export const state = { workouts: [], exerciseRef: [], bodyMetrics: [], workoutTypes: [], metricTypes: [], clients: [], // каждый клиент: {id, sync_id, full_name, birth_date, goal, color} expandedWorkoutId: null, expandedExerciseId: null, nextId: 1, mode: 'personal', currentClientId: null, // больше не используется глобально, но оставим для совместимости }; export function loadState() { const saved = localStorage.getItem(STORAGE_KEY); if (saved) { try { const parsed = JSON.parse(saved); // Объединяем, чтобы не потерять новые поля при обновлении версии Object.assign(state, parsed); if (!state.workoutTypes) state.workoutTypes = []; if (!state.metricTypes) state.metricTypes = []; if (!state.clients) state.clients = []; if (!state.mode) state.mode = 'personal'; } catch (e) { console.error('Failed to load state', e); } } } export function saveState() { localStorage.setItem(STORAGE_KEY, JSON.stringify(state)); updateSyncStatus(); } export function genId() { return (state.nextId++).toString(); } // Генерация UUID v4 для sync_id (идемпотентность на бэкенде) export function generateUUID() { return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => { const r = Math.random() * 16 | 0; const v = c === 'x' ? r : (r & 0x3 | 0x8); return v.toString(16); }); } export function updateSyncStatus() { const dirty = state.workouts.filter(w => !w.synced); const el = document.getElementById('sync-status'); if (!el) return; if (dirty.length === 0) { el.textContent = '● Всё синхронизировано'; el.className = 'sync-status synced'; } else { el.textContent = `● ${dirty.length} не сохран.`; el.className = 'sync-status pending'; } }