front-back integrated
This commit is contained in:
+25
-3
@@ -1,12 +1,22 @@
|
||||
const STORAGE_KEY = 'gym_tracker_v5';
|
||||
const STORAGE_KEY = 'gym_tracker_v6';
|
||||
|
||||
export const state = {
|
||||
workouts: [],
|
||||
exerciseRef: [],
|
||||
bodyMetrics: [],
|
||||
|
||||
// Справочники с бэкенда
|
||||
workoutTypes: [],
|
||||
metricTypes: [],
|
||||
clients: [],
|
||||
|
||||
expandedWorkoutId: null,
|
||||
expandedExerciseId: null,
|
||||
nextId: 1,
|
||||
|
||||
// Режимы: 'personal' (по умолчанию) или 'trainer'
|
||||
mode: 'personal',
|
||||
currentClientId: null, // В личном режиме null, в режиме тренера - ID клиента
|
||||
};
|
||||
|
||||
export function loadState() {
|
||||
@@ -14,9 +24,12 @@ export function loadState() {
|
||||
if (saved) {
|
||||
try {
|
||||
const parsed = JSON.parse(saved);
|
||||
// Объединяем, чтобы не потерять новые поля при обновлении версии
|
||||
Object.assign(state, parsed);
|
||||
if (!state.exerciseRef) state.exerciseRef = [];
|
||||
if (!state.bodyMetrics) state.bodyMetrics = [];
|
||||
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);
|
||||
}
|
||||
@@ -32,6 +45,15 @@ 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');
|
||||
|
||||
Reference in New Issue
Block a user