mirror of
https://github.com/R0m1k3/LogiFlow.git
synced 2026-10-21 22:18:17 +02:00
Add weather information display and configuration options
Integrate weather data fetching, display in a widget, and provide a settings page for configuration. Replit-Commit-Author: Agent Replit-Commit-Session-Id: d43bd811-9372-45a7-8ac9-4a954c0538e1 Replit-Commit-Checkpoint-Type: full_checkpoint Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/1957c339-2757-4d1f-8e92-e9f71a1ce58e/d43bd811-9372-45a7-8ac9-4a954c0538e1/BIZe1t3
This commit is contained in:
1 parent
48bfc884ed
commit
e70e860097
9 files changed
+863
-4
No files matched your search
+116
-1
@@ -36,12 +36,15 @@ import {
|
||||
insertTaskSchema,
|
||||
insertNocodbConfigSchema,
|
||||
insertSavTicketSchema,
|
||||
insertSavTicketHistorySchema
|
||||
insertSavTicketHistorySchema,
|
||||
insertWeatherDataSchema,
|
||||
insertWeatherSettingsSchema
|
||||
} from "@shared/schema";
|
||||
import { hasPermission } from "@shared/permissions";
|
||||
import { z } from "zod";
|
||||
import { invoiceVerificationService } from "./invoiceVerification";
|
||||
import { backupService } from "./backupService";
|
||||
import { weatherService } from "./weatherService.js";
|
||||
|
||||
export async function registerRoutes(app: Express): Promise<Server> {
|
||||
// Health check endpoint for Docker
|
||||
@@ -2753,6 +2756,118 @@ RÉSUMÉ DU SCAN
|
||||
}
|
||||
});
|
||||
|
||||
// Weather routes
|
||||
app.get('/api/weather/settings', isAuthenticated, requireAdmin, async (req: any, res) => {
|
||||
try {
|
||||
const settings = await storage.getWeatherSettings();
|
||||
res.json(settings);
|
||||
} catch (error) {
|
||||
console.error("Error fetching weather settings:", error);
|
||||
res.status(500).json({ message: "Failed to fetch weather settings" });
|
||||
}
|
||||
});
|
||||
|
||||
app.post('/api/weather/settings', isAuthenticated, requireAdmin, async (req: any, res) => {
|
||||
try {
|
||||
const data = insertWeatherSettingsSchema.parse(req.body);
|
||||
const settings = await storage.createWeatherSettings(data);
|
||||
res.json(settings);
|
||||
} catch (error) {
|
||||
console.error("Error creating weather settings:", error);
|
||||
if (error instanceof z.ZodError) {
|
||||
return res.status(400).json({ message: "Validation error", errors: error.errors });
|
||||
}
|
||||
res.status(500).json({ message: "Failed to create weather settings" });
|
||||
}
|
||||
});
|
||||
|
||||
app.put('/api/weather/settings/:id', isAuthenticated, requireAdmin, async (req: any, res) => {
|
||||
try {
|
||||
const id = parseInt(req.params.id);
|
||||
const data = insertWeatherSettingsSchema.partial().parse(req.body);
|
||||
const settings = await storage.updateWeatherSettings(id, data);
|
||||
res.json(settings);
|
||||
} catch (error) {
|
||||
console.error("Error updating weather settings:", error);
|
||||
if (error instanceof z.ZodError) {
|
||||
return res.status(400).json({ message: "Validation error", errors: error.errors });
|
||||
}
|
||||
res.status(500).json({ message: "Failed to update weather settings" });
|
||||
}
|
||||
});
|
||||
|
||||
app.post('/api/weather/test-connection', isAuthenticated, requireAdmin, async (req: any, res) => {
|
||||
try {
|
||||
const { apiKey, location } = req.body;
|
||||
|
||||
if (!apiKey || !location) {
|
||||
return res.status(400).json({ message: "API key and location are required" });
|
||||
}
|
||||
|
||||
const result = await weatherService.testApiConnection(apiKey, location);
|
||||
res.json(result);
|
||||
} catch (error) {
|
||||
console.error("Error testing weather API connection:", error);
|
||||
res.status(500).json({ message: "Failed to test API connection" });
|
||||
}
|
||||
});
|
||||
|
||||
app.get('/api/weather/current', isAuthenticated, async (req: any, res) => {
|
||||
try {
|
||||
const settings = await storage.getWeatherSettings();
|
||||
|
||||
if (!settings || !settings.isActive) {
|
||||
return res.status(404).json({ message: "Weather service not configured or disabled" });
|
||||
}
|
||||
|
||||
const today = new Date().toISOString().split('T')[0];
|
||||
const previousYearDate = weatherService.getPreviousYearDate();
|
||||
|
||||
// Check if we already have today's data
|
||||
let currentYearData = await storage.getWeatherData(today, true);
|
||||
let previousYearData = await storage.getWeatherData(previousYearDate, false);
|
||||
|
||||
// Fetch current year data if not in cache
|
||||
if (!currentYearData) {
|
||||
console.log("🌤️ Fetching current weather data from API");
|
||||
const apiData = await weatherService.fetchCurrentWeather(settings);
|
||||
if (apiData) {
|
||||
const weatherData = weatherService.convertApiDataToWeatherData(apiData, settings.location, true);
|
||||
if (weatherData) {
|
||||
currentYearData = await storage.createWeatherData(weatherData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Fetch previous year data if not in cache
|
||||
if (!previousYearData) {
|
||||
console.log("🌤️ Fetching previous year weather data from API");
|
||||
const apiData = await weatherService.fetchPreviousYearWeather(settings, previousYearDate);
|
||||
if (apiData) {
|
||||
const weatherData = weatherService.convertApiDataToWeatherData(apiData, settings.location, false);
|
||||
if (weatherData) {
|
||||
previousYearData = await storage.createWeatherData(weatherData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
res.json({
|
||||
currentYear: currentYearData ? {
|
||||
...currentYearData,
|
||||
icon: weatherService.getWeatherIcon(currentYearData.icon)
|
||||
} : null,
|
||||
previousYear: previousYearData ? {
|
||||
...previousYearData,
|
||||
icon: weatherService.getWeatherIcon(previousYearData.icon)
|
||||
} : null,
|
||||
location: settings.location
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("Error fetching weather data:", error);
|
||||
res.status(500).json({ message: "Failed to fetch weather data" });
|
||||
}
|
||||
});
|
||||
|
||||
// Create server instance
|
||||
const httpServer = createServer(app);
|
||||
|
||||
|
||||
Reference in new issue
Block a user