This commit is contained in:
dios.one
2026-04-21 18:00:30 +07:00
parent 2173a765c9
commit 23dc306f12
67 changed files with 10302 additions and 67 deletions
+242
View File
@@ -0,0 +1,242 @@
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;
}