243 lines
6.1 KiB
JavaScript
243 lines
6.1 KiB
JavaScript
import { supabase } from './supabase';
|
|
import * as offline from './offlineStorage';
|
|
import { generateHabitsFromIdentity } from '../utils/helpers';
|
|
import { todayISO, addDays } from '../utils/date';
|
|
|
|
// Must match authService.js
|
|
const USE_OFFLINE = true;
|
|
|
|
// ========================
|
|
// GET IDENTITY
|
|
// ========================
|
|
export async function getIdentity(userId) {
|
|
if (USE_OFFLINE) {
|
|
return offline.getOne('identities', { user_id: userId });
|
|
}
|
|
|
|
const { data, error } = await supabase
|
|
.from('identities')
|
|
.select('*')
|
|
.eq('user_id', userId)
|
|
.order('created_at', { ascending: false })
|
|
.limit(1)
|
|
.single();
|
|
|
|
if (error && error.code !== 'PGRST116') throw error;
|
|
return data || null;
|
|
}
|
|
|
|
// ========================
|
|
// CREATE IDENTITY
|
|
// ========================
|
|
export async function createIdentity(userId, title, description, customHabits, storyText) {
|
|
const startDate = todayISO();
|
|
const endDate = addDays(new Date(), 40);
|
|
|
|
if (USE_OFFLINE) {
|
|
const identity = await offline.insert('identities', {
|
|
user_id: userId,
|
|
title,
|
|
description: description || title,
|
|
story_text: storyText || '',
|
|
start_date: startDate,
|
|
end_date: endDate,
|
|
status: 'active',
|
|
});
|
|
|
|
const habitsList = customHabits && customHabits.length > 0
|
|
? customHabits
|
|
: generateHabitsFromIdentity(title);
|
|
|
|
const habitsToInsert = habitsList.map((h) => ({
|
|
identity_id: identity.id,
|
|
title: h.title,
|
|
description: h.description || '',
|
|
}));
|
|
|
|
const habits = await offline.insertMany('habits', habitsToInsert);
|
|
|
|
await offline.insert('stats', {
|
|
identity_id: identity.id,
|
|
discipline_score: 0,
|
|
focus_score: 0,
|
|
consistency_score: 0,
|
|
});
|
|
|
|
return { identity, habits };
|
|
}
|
|
|
|
// --- Supabase path ---
|
|
const { data, error } = await supabase
|
|
.from('identities')
|
|
.insert({
|
|
user_id: userId,
|
|
title,
|
|
description: description || title,
|
|
story_text: storyText || '',
|
|
start_date: startDate,
|
|
end_date: endDate,
|
|
status: 'active',
|
|
})
|
|
.select()
|
|
.single();
|
|
|
|
if (error) throw error;
|
|
|
|
const habitsList = customHabits && customHabits.length > 0
|
|
? customHabits
|
|
: generateHabitsFromIdentity(title);
|
|
|
|
const habitsToInsert = habitsList.map((h) => ({
|
|
identity_id: data.id,
|
|
title: h.title,
|
|
description: h.description || '',
|
|
}));
|
|
|
|
const { data: habits, error: habitsError } = await supabase
|
|
.from('habits')
|
|
.insert(habitsToInsert)
|
|
.select();
|
|
|
|
if (habitsError) throw habitsError;
|
|
|
|
await supabase.from('stats').insert({
|
|
identity_id: data.id,
|
|
discipline_score: 0,
|
|
focus_score: 0,
|
|
consistency_score: 0,
|
|
});
|
|
|
|
return { identity: data, habits: habits || [] };
|
|
}
|
|
|
|
// ========================
|
|
// DAILY LOGS
|
|
// ========================
|
|
export async function getDailyLogs(identityId) {
|
|
if (USE_OFFLINE) {
|
|
const logs = await offline.getAll('daily_logs', { identity_id: identityId });
|
|
return logs.sort((a, b) => a.day_number - b.day_number);
|
|
}
|
|
|
|
const { data, error } = await supabase
|
|
.from('daily_logs')
|
|
.select('*')
|
|
.eq('identity_id', identityId)
|
|
.order('day_number', { ascending: true });
|
|
|
|
if (error) throw error;
|
|
return data || [];
|
|
}
|
|
|
|
export async function saveDailyLog(identityId, dayNumber, identityCheck, note) {
|
|
const today = todayISO();
|
|
|
|
if (USE_OFFLINE) {
|
|
await offline.upsert(
|
|
'daily_logs',
|
|
{ identity_id: identityId, date: today },
|
|
{ day_number: dayNumber, identity_check: identityCheck, note: note || '' }
|
|
);
|
|
|
|
// Update stats
|
|
const scoreAdd = identityCheck === 'yes' ? 3 : identityCheck === 'almost' ? 1 : 0;
|
|
if (scoreAdd > 0) {
|
|
const stats = await offline.getOne('stats', { identity_id: identityId });
|
|
if (stats) {
|
|
await offline.update('stats', { id: stats.id }, {
|
|
discipline_score: stats.discipline_score + scoreAdd,
|
|
consistency_score: stats.consistency_score + (identityCheck === 'yes' ? 2 : 1),
|
|
focus_score: stats.focus_score + scoreAdd,
|
|
});
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
// --- Supabase path ---
|
|
const { data: existing } = await supabase
|
|
.from('daily_logs')
|
|
.select('id')
|
|
.eq('identity_id', identityId)
|
|
.eq('date', today)
|
|
.maybeSingle();
|
|
|
|
if (existing) {
|
|
const { error } = await supabase
|
|
.from('daily_logs')
|
|
.update({ identity_check: identityCheck, note: note || '' })
|
|
.eq('id', existing.id);
|
|
if (error) throw error;
|
|
} else {
|
|
const { error } = await supabase
|
|
.from('daily_logs')
|
|
.insert({
|
|
identity_id: identityId,
|
|
date: today,
|
|
day_number: dayNumber,
|
|
identity_check: identityCheck,
|
|
note: note || '',
|
|
});
|
|
if (error) throw error;
|
|
}
|
|
|
|
const scoreAdd = identityCheck === 'yes' ? 3 : identityCheck === 'almost' ? 1 : 0;
|
|
if (scoreAdd > 0) {
|
|
const { data: stats } = await supabase
|
|
.from('stats')
|
|
.select('*')
|
|
.eq('identity_id', identityId)
|
|
.maybeSingle();
|
|
|
|
if (stats) {
|
|
await supabase
|
|
.from('stats')
|
|
.update({
|
|
discipline_score: stats.discipline_score + scoreAdd,
|
|
consistency_score: stats.consistency_score + (identityCheck === 'yes' ? 2 : 1),
|
|
focus_score: stats.focus_score + scoreAdd,
|
|
})
|
|
.eq('id', stats.id);
|
|
}
|
|
}
|
|
}
|
|
|
|
// ========================
|
|
// STATS
|
|
// ========================
|
|
export async function getStats(identityId) {
|
|
if (USE_OFFLINE) {
|
|
return offline.getOne('stats', { identity_id: identityId });
|
|
}
|
|
|
|
const { data, error } = await supabase
|
|
.from('stats')
|
|
.select('*')
|
|
.eq('identity_id', identityId)
|
|
.single();
|
|
|
|
if (error && error.code !== 'PGRST116') throw error;
|
|
return data || null;
|
|
}
|
|
|
|
// ========================
|
|
// GAME SESSIONS
|
|
// ========================
|
|
export async function saveGameScore(identityId, gameType, score) {
|
|
if (USE_OFFLINE) {
|
|
await offline.insert('game_sessions', {
|
|
identity_id: identityId,
|
|
game_type: gameType,
|
|
score,
|
|
});
|
|
return;
|
|
}
|
|
|
|
const { error } = await supabase.from('game_sessions').insert({
|
|
identity_id: identityId,
|
|
game_type: gameType,
|
|
score,
|
|
});
|
|
if (error) throw error;
|
|
}
|