Set up project configuration and base UI components

Initializes the project with necessary configurations, including Replit settings and a .gitignore file. It also introduces foundational UI components for the application, such as buttons, dialogs, and layout elements, likely for the Pomodoro timer application.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 59a5ae27-3c71-459b-b42f-fe14121bf9c3
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/3007b6f6-d03b-45e1-9ed1-7ce8de18ea24/59a5ae27-3c71-459b-b42f-fe14121bf9c3/Uupe4F4
This commit is contained in:
ingecarlosgutie
2025-08-31 20:11:52 +00:00
parent 64aa1e69a0
commit 80595e7002
89 changed files with 17597 additions and 0 deletions

171
server/routes.ts Normal file
View File

@@ -0,0 +1,171 @@
import type { Express } from "express";
import { createServer, type Server } from "http";
import { storage } from "./storage";
import { insertSessionSchema } from "@shared/schema";
import { z } from "zod";
export async function registerRoutes(app: Express): Promise<Server> {
// Create session
app.post("/api/sessions", async (req, res) => {
try {
const sessionData = insertSessionSchema.parse(req.body);
const session = await storage.createSession(sessionData);
// Update device activity
await storage.updateDeviceProfileActivity(sessionData.deviceId);
res.status(201).json({ ok: true, id: session.id });
} catch (error) {
if (error instanceof z.ZodError) {
return res.status(400).json({ message: "Invalid session data", errors: error.errors });
}
res.status(500).json({ message: "Failed to create session" });
}
});
// Get suggestions for device
app.get("/api/suggestions", async (req, res) => {
try {
const deviceId = req.query.deviceId as string;
if (!deviceId) {
return res.status(400).json({ message: "Device ID is required" });
}
// Get recent sessions (last 7 days)
const sevenDaysAgo = new Date();
sevenDaysAgo.setDate(sevenDaysAgo.getDate() - 7);
const recentSessions = await storage.getSessionsInDateRange(deviceId, sevenDaysAgo, new Date());
const suggestions = generateSuggestions(recentSessions);
res.json({ suggestions });
} catch (error) {
res.status(500).json({ message: "Failed to get suggestions" });
}
});
// Get stats summary
app.get("/api/stats/summary", async (req, res) => {
try {
const deviceId = req.query.deviceId as string;
if (!deviceId) {
return res.status(400).json({ message: "Device ID is required" });
}
const sevenDaysAgo = new Date();
sevenDaysAgo.setDate(sevenDaysAgo.getDate() - 7);
const thirtyDaysAgo = new Date();
thirtyDaysAgo.setDate(thirtyDaysAgo.getDate() - 30);
const last7dSessions = await storage.getSessionsInDateRange(deviceId, sevenDaysAgo, new Date());
const last30dSessions = await storage.getSessionsInDateRange(deviceId, thirtyDaysAgo, new Date());
const last7d = calculateStats(last7dSessions.filter(s => s.type === 'focus'));
const last30d = calculateStats(last30dSessions.filter(s => s.type === 'focus'));
res.json({ last7d, last30d });
} catch (error) {
res.status(500).json({ message: "Failed to get stats" });
}
});
const httpServer = createServer(app);
return httpServer;
}
function generateSuggestions(sessions: any[]) {
const focusSessions = sessions.filter(s => s.type === 'focus');
if (focusSessions.length === 0) {
return [
{ minutes: 25, reason: "Classic Pomodoro technique - great for starting out." },
{ minutes: 15, reason: "Short sprints help build focus habits." },
{ minutes: 40, reason: "Extended sessions for deep work." }
];
}
const completedSessions = focusSessions.filter(s => s.completed);
const completionRate = completedSessions.length / focusSessions.length;
// Analyze successful durations
const successfulDurations = completedSessions.map(s => s.intendedMinutes);
const avgSuccessfulDuration = successfulDurations.reduce((a, b) => a + b, 0) / successfulDurations.length;
// Analyze time of day patterns
const now = new Date();
const currentHour = now.getHours();
const timeOfDaySuccess = getTimeOfDaySuccess(completedSessions, currentHour);
const suggestions = [];
// Primary suggestion based on completion rate
if (completionRate >= 0.8) {
suggestions.push({
minutes: Math.round(avgSuccessfulDuration),
reason: `Your 7-day completion rate is ${Math.round(completionRate * 100)}% at ${Math.round(avgSuccessfulDuration)}m.`
});
} else {
suggestions.push({
minutes: 25,
reason: "Classic 25min sessions have proven effective for most users."
});
}
// Time-based suggestion
if (timeOfDaySuccess.avgDuration > 0) {
suggestions.push({
minutes: Math.round(timeOfDaySuccess.avgDuration),
reason: `${getTimeOfDayLabel(currentHour)}: best focus avg ${Math.round(timeOfDaySuccess.avgDuration - 3)}${Math.round(timeOfDaySuccess.avgDuration + 3)}m.`
});
}
// Interruption-based suggestion
const avgInterruptions = focusSessions.reduce((sum, s) => sum + s.interruptions, 0) / focusSessions.length;
if (avgInterruptions > 1) {
suggestions.push({
minutes: 15,
reason: "High interruption periods benefit from short sprints."
});
} else {
suggestions.push({
minutes: 40,
reason: "Low interruption environment - try longer deep work sessions."
});
}
return suggestions.slice(0, 3);
}
function calculateStats(focusSessions: any[]) {
const completed = focusSessions.filter(s => s.completed);
const completionRate = focusSessions.length > 0 ? completed.length / focusSessions.length : 0;
const avgFocusMin = completed.length > 0
? completed.reduce((sum, s) => sum + s.intendedMinutes, 0) / completed.length
: 0;
return {
sessions: focusSessions.length,
completionRate: Math.round(completionRate * 100) / 100,
avgFocusMin: Math.round(avgFocusMin)
};
}
function getTimeOfDaySuccess(sessions: any[], currentHour: number) {
const timeRangeSessions = sessions.filter(s => {
const sessionHour = new Date(s.startedAt).getHours();
return Math.abs(sessionHour - currentHour) <= 2;
});
if (timeRangeSessions.length === 0) {
return { avgDuration: 0 };
}
const avgDuration = timeRangeSessions.reduce((sum, s) => sum + s.intendedMinutes, 0) / timeRangeSessions.length;
return { avgDuration };
}
function getTimeOfDayLabel(hour: number) {
if (hour >= 6 && hour < 12) return "Mornings";
if (hour >= 12 && hour < 17) return "Afternoons";
if (hour >= 17 && hour < 21) return "Evenings";
return "Late hours";
}