UUID generation fixed

This commit is contained in:
AG
2025-11-28 18:20:22 +02:00
parent 245b8d3961
commit 4c632e164e
7 changed files with 26 additions and 10 deletions

View File

@@ -12,6 +12,7 @@ import { TabView, WorkoutSession, WorkoutSet, WorkoutPlan, User, Language } from
import { getSessions, saveSession, deleteSession, getPlans } from './services/storage'; import { getSessions, saveSession, deleteSession, getPlans } from './services/storage';
import { getCurrentUserProfile, getMe } from './services/auth'; import { getCurrentUserProfile, getMe } from './services/auth';
import { getSystemLanguage } from './services/i18n'; import { getSystemLanguage } from './services/i18n';
import { generateId } from './utils/uuid';
function App() { function App() {
const [currentUser, setCurrentUser] = useState<User | null>(null); const [currentUser, setCurrentUser] = useState<User | null>(null);
@@ -86,7 +87,7 @@ function App() {
const currentWeight = startWeight || profile?.weight || 70; const currentWeight = startWeight || profile?.weight || 70;
const newSession: WorkoutSession = { const newSession: WorkoutSession = {
id: crypto.randomUUID(), id: generateId(),
startTime: Date.now(), startTime: Date.now(),
userBodyWeight: currentWeight, userBodyWeight: currentWeight,
sets: [], sets: [],

View File

@@ -5,6 +5,7 @@ import { createFitnessChat } from '../services/geminiService';
import { WorkoutSession, Language, UserProfile, WorkoutPlan } from '../types'; import { WorkoutSession, Language, UserProfile, WorkoutPlan } from '../types';
import { Chat, GenerateContentResponse } from '@google/genai'; import { Chat, GenerateContentResponse } from '@google/genai';
import { t } from '../services/i18n'; import { t } from '../services/i18n';
import { generateId } from '../utils/uuid';
interface AICoachProps { interface AICoachProps {
history: WorkoutSession[]; history: WorkoutSession[];
@@ -53,7 +54,7 @@ const AICoach: React.FC<AICoachProps> = ({ history, userProfile, plans, lang })
const handleSend = async () => { const handleSend = async () => {
if (!input.trim() || !chatSessionRef.current || loading) return; if (!input.trim() || !chatSessionRef.current || loading) return;
const userMsg: Message = { id: crypto.randomUUID(), role: 'user', text: input }; const userMsg: Message = { id: generateId(), role: 'user', text: input };
setMessages(prev => [...prev, userMsg]); setMessages(prev => [...prev, userMsg]);
setInput(''); setInput('');
setLoading(true); setLoading(true);
@@ -63,7 +64,7 @@ const AICoach: React.FC<AICoachProps> = ({ history, userProfile, plans, lang })
const text = result.text; const text = result.text;
const aiMsg: Message = { const aiMsg: Message = {
id: crypto.randomUUID(), id: generateId(),
role: 'model', role: 'model',
text: text || "Error generating response." text: text || "Error generating response."
}; };
@@ -80,7 +81,7 @@ const AICoach: React.FC<AICoachProps> = ({ history, userProfile, plans, lang })
errorText = err.message; errorText = err.message;
} }
} }
setMessages(prev => [...prev, { id: crypto.randomUUID(), role: 'model', text: errorText }]); setMessages(prev => [...prev, { id: generateId(), role: 'model', text: errorText }]);
} finally { } finally {
setLoading(false); setLoading(false);
} }

View File

@@ -2,6 +2,7 @@ import React, { useState } from 'react';
import { X, Dumbbell, User, Flame, Timer as TimerIcon, ArrowUp, ArrowRight, Footprints, Ruler, Percent } from 'lucide-react'; import { X, Dumbbell, User, Flame, Timer as TimerIcon, ArrowUp, ArrowRight, Footprints, Ruler, Percent } from 'lucide-react';
import { ExerciseDef, ExerciseType, Language } from '../types'; import { ExerciseDef, ExerciseType, Language } from '../types';
import { t } from '../services/i18n'; import { t } from '../services/i18n';
import { generateId } from '../utils/uuid';
import FilledInput from './FilledInput'; import FilledInput from './FilledInput';
interface ExerciseModalProps { interface ExerciseModalProps {
@@ -43,7 +44,7 @@ const ExerciseModal: React.FC<ExerciseModalProps> = ({ isOpen, onClose, onSave,
} }
const newEx: ExerciseDef = { const newEx: ExerciseDef = {
id: crypto.randomUUID(), id: generateId(),
name: trimmedName, name: trimmedName,
type: newType, type: newType,
...(newType === ExerciseType.BODYWEIGHT && { bodyWeightPercentage: parseFloat(newBwPercentage) || 100 }) ...(newType === ExerciseType.BODYWEIGHT && { bodyWeightPercentage: parseFloat(newBwPercentage) || 100 })

View File

@@ -4,6 +4,7 @@ import { Plus, Trash2, PlayCircle, Dumbbell, Save, X, ChevronRight, List, ArrowU
import { WorkoutPlan, ExerciseDef, PlannedSet, Language, ExerciseType } from '../types'; import { WorkoutPlan, ExerciseDef, PlannedSet, Language, ExerciseType } from '../types';
import { getPlans, savePlan, deletePlan, getExercises, saveExercise } from '../services/storage'; import { getPlans, savePlan, deletePlan, getExercises, saveExercise } from '../services/storage';
import { t } from '../services/i18n'; import { t } from '../services/i18n';
import { generateId } from '../utils/uuid';
interface PlansProps { interface PlansProps {
userId: string; userId: string;
@@ -68,7 +69,7 @@ const Plans: React.FC<PlansProps> = ({ userId, onStartPlan, lang }) => {
}, [userId]); }, [userId]);
const handleCreateNew = () => { const handleCreateNew = () => {
setEditId(crypto.randomUUID()); setEditId(generateId());
setName(''); setName('');
setDescription(''); setDescription('');
setSteps([]); setSteps([]);
@@ -103,7 +104,7 @@ const Plans: React.FC<PlansProps> = ({ userId, onStartPlan, lang }) => {
const addStep = (ex: ExerciseDef) => { const addStep = (ex: ExerciseDef) => {
const newStep: PlannedSet = { const newStep: PlannedSet = {
id: crypto.randomUUID(), id: generateId(),
exerciseId: ex.id, exerciseId: ex.id,
exerciseName: ex.name, exerciseName: ex.name,
exerciseType: ex.type, exerciseType: ex.type,
@@ -116,7 +117,7 @@ const Plans: React.FC<PlansProps> = ({ userId, onStartPlan, lang }) => {
const handleCreateExercise = async () => { const handleCreateExercise = async () => {
if (!newExName.trim()) return; if (!newExName.trim()) return;
const newEx: ExerciseDef = { const newEx: ExerciseDef = {
id: crypto.randomUUID(), id: generateId(),
name: newExName.trim(), name: newExName.trim(),
type: newExType, type: newExType,
...(newExType === ExerciseType.BODYWEIGHT && { bodyWeightPercentage: parseFloat(newExBwPercentage) || 100 }) ...(newExType === ExerciseType.BODYWEIGHT && { bodyWeightPercentage: parseFloat(newExBwPercentage) || 100 })

View File

@@ -5,6 +5,7 @@ import { WorkoutSession, WorkoutSet, ExerciseDef, ExerciseType, WorkoutPlan, Lan
import { getExercises, getLastSetForExercise, saveExercise, getPlans } from '../services/storage'; import { getExercises, getLastSetForExercise, saveExercise, getPlans } from '../services/storage';
import { getCurrentUserProfile } from '../services/auth'; import { getCurrentUserProfile } from '../services/auth';
import { t } from '../services/i18n'; import { t } from '../services/i18n';
import { generateId } from '../utils/uuid';
interface TrackerProps { interface TrackerProps {
userId: string; userId: string;
@@ -151,7 +152,7 @@ const Tracker: React.FC<TrackerProps> = ({ userId, userWeight, activeSession, ac
if (!activeSession || !selectedExercise) return; if (!activeSession || !selectedExercise) return;
const newSet: WorkoutSet = { const newSet: WorkoutSet = {
id: crypto.randomUUID(), id: generateId(),
exerciseId: selectedExercise.id, exerciseId: selectedExercise.id,
exerciseName: selectedExercise.name, exerciseName: selectedExercise.name,
type: selectedExercise.type, type: selectedExercise.type,

View File

@@ -1,5 +1,6 @@
import { WorkoutSession, UserProfile, WorkoutPlan } from '../types'; import { WorkoutSession, UserProfile, WorkoutPlan } from '../types';
import { api } from './api'; import { api } from './api';
import { generateId } from '../utils/uuid';
interface FitnessChatOptions { interface FitnessChatOptions {
history: WorkoutSession[]; history: WorkoutSession[];
@@ -16,7 +17,7 @@ export const createFitnessChat = (
plans?: WorkoutPlan[] plans?: WorkoutPlan[]
): any => { ): any => {
// Generate a unique session ID for this chat instance // Generate a unique session ID for this chat instance
const sessionId = crypto.randomUUID(); const sessionId = generateId();
// Summarize workout history // Summarize workout history
const workoutSummary = history.slice(0, 20).map(s => ({ const workoutSummary = history.slice(0, 20).map(s => ({

10
utils/uuid.ts Normal file
View File

@@ -0,0 +1,10 @@
export const generateId = (): string => {
if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {
return crypto.randomUUID();
}
// Fallback for non-secure contexts
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
return v.toString(16);
});
};