1st version
This commit is contained in:
200
source/app.js
200
source/app.js
@@ -1,10 +1,194 @@
|
||||
import React from 'react';
|
||||
import {Text} from 'ink';
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { Text, Box } from 'ink';
|
||||
import fetch from 'node-fetch';
|
||||
|
||||
export default function App({name = 'Stranger'}) {
|
||||
return (
|
||||
<Text>
|
||||
Hello, <Text color="green">{name}</Text>
|
||||
</Text>
|
||||
);
|
||||
const locations = {
|
||||
Nancy: { latitude: 48.6921, longitude: 6.1844 },
|
||||
Paris: { latitude: 48.8566, longitude: 2.3522 }
|
||||
};
|
||||
|
||||
function formatTime(date) {
|
||||
return date.toLocaleTimeString('fr-FR', { hour12: false });
|
||||
}
|
||||
|
||||
function formatDate(date) {
|
||||
return date.toLocaleDateString('fr-FR', {
|
||||
weekday: 'long',
|
||||
year: 'numeric',
|
||||
month: 'long',
|
||||
day: 'numeric'
|
||||
});
|
||||
}
|
||||
|
||||
function formatDateTimeUTC(utcString) {
|
||||
const date = new Date(utcString);
|
||||
return {
|
||||
date: formatDate(date),
|
||||
time: formatTime(date)
|
||||
};
|
||||
}
|
||||
|
||||
async function fetchWeather(lat, lon) {
|
||||
const url = `https://api.open-meteo.com/v1/forecast?latitude=${lat}&longitude=${lon}¤t_weather=true&temperature_unit=celsius&timezone=Europe/Paris`;
|
||||
const response = await fetch(url);
|
||||
const data = await response.json();
|
||||
return data.current_weather;
|
||||
}
|
||||
|
||||
const weatherCodeMap = {
|
||||
0: { desc: 'Ciel clair', color: 'yellow' },
|
||||
1: { desc: 'Principalement clair', color: 'yellow' },
|
||||
2: { desc: 'Partiellement nuageux', color: 'cyan' },
|
||||
3: { desc: 'Couvert', color: 'gray' },
|
||||
45: { desc: 'Brouillard', color: 'gray' },
|
||||
48: { desc: 'Brouillard givrant', color: 'gray' },
|
||||
51: { desc: 'Bruine légère', color: 'blue' },
|
||||
53: { desc: 'Bruine modérée', color: 'blue' },
|
||||
55: { desc: 'Bruine dense', color: 'blue' },
|
||||
56: { desc: 'Bruine verglaçante légère', color: 'blue' },
|
||||
57: { desc: 'Bruine verglaçante dense', color: 'blue' },
|
||||
61: { desc: 'Pluie faible', color: 'blue' },
|
||||
63: { desc: 'Pluie modérée', color: 'blue' },
|
||||
65: { desc: 'Pluie forte', color: 'blue' },
|
||||
66: { desc: 'Pluie verglaçante légère', color: 'blue' },
|
||||
67: { desc: 'Pluie verglaçante forte', color: 'blue' },
|
||||
71: { desc: 'Chute de neige légère', color: 'white' },
|
||||
73: { desc: 'Chute de neige modérée', color: 'white' },
|
||||
75: { desc: 'Chute de neige forte', color: 'white' },
|
||||
77: { desc: 'Grains de neige', color: 'white' },
|
||||
80: { desc: 'Averses de pluie faibles', color: 'blue' },
|
||||
81: { desc: 'Averses de pluie modérées', color: 'blue' },
|
||||
82: { desc: 'Averses de pluie violentes', color: 'blue' },
|
||||
85: { desc: 'Averses de neige faibles', color: 'white' },
|
||||
86: { desc: 'Averses de neige fortes', color: 'white' },
|
||||
95: { desc: 'Orage', color: 'magenta' },
|
||||
96: { desc: 'Orage avec faible grêle', color: 'magenta' },
|
||||
99: { desc: 'Orage avec forte grêle', color: 'magenta' }
|
||||
|
||||
};
|
||||
|
||||
export default function App({ name = 'Mathias' }) {
|
||||
const [now, setNow] = useState(new Date());
|
||||
const [weatherNancy, setWeatherNancy] = useState(null);
|
||||
const [weatherParis, setWeatherParis] = useState(null);
|
||||
|
||||
const [matchesInter, setMatchesInter] = useState(null);
|
||||
const [matchesParis, setMatchesParis] = useState(null);
|
||||
|
||||
const INTER_ID = 6684; // SC Internacional team id
|
||||
const PARIS_ID = 1045; // Paris FC team id
|
||||
|
||||
useEffect(() => {
|
||||
const timer = setInterval(() => {
|
||||
setNow(new Date());
|
||||
}, 1000);
|
||||
|
||||
async function updateWeather() {
|
||||
try {
|
||||
const nancyData = await fetchWeather(locations.Nancy.latitude, locations.Nancy.longitude);
|
||||
const parisData = await fetchWeather(locations.Paris.latitude, locations.Paris.longitude);
|
||||
setWeatherNancy(nancyData);
|
||||
setWeatherParis(parisData);
|
||||
} catch (error) {
|
||||
// gestion d'erreur météo
|
||||
}
|
||||
}
|
||||
|
||||
async function fetchMatches(teamId, setMatches) {
|
||||
try {
|
||||
const response = await fetch(
|
||||
`https://api.football-data.org/v4/teams/${teamId}/matches?status=SCHEDULED`,
|
||||
{
|
||||
headers: { "X-Auth-Token": "1535f68086e542528841b5e276f50b45" } // Remplace par ton token
|
||||
}
|
||||
);
|
||||
const data = await response.json();
|
||||
|
||||
const filtered = data.matches.map(match => {
|
||||
let opponent, homeAway;
|
||||
if (match.homeTeam.id === teamId) {
|
||||
opponent = match.awayTeam.name;
|
||||
homeAway = 'Home';
|
||||
} else if (match.awayTeam.id === teamId) {
|
||||
opponent = match.homeTeam.name;
|
||||
homeAway = 'Away';
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
const { date, time } = formatDateTimeUTC(match.utcDate);
|
||||
return { date, time, opponent, homeAway };
|
||||
}).filter(Boolean);
|
||||
|
||||
setMatches(filtered);
|
||||
} catch (error) {
|
||||
setMatches([]);
|
||||
}
|
||||
}
|
||||
|
||||
updateWeather();
|
||||
fetchMatches(INTER_ID, setMatchesInter);
|
||||
fetchMatches(PARIS_ID, setMatchesParis);
|
||||
|
||||
const weatherInterval = setInterval(updateWeather, 60000);
|
||||
|
||||
return () => {
|
||||
clearInterval(timer);
|
||||
clearInterval(weatherInterval);
|
||||
};
|
||||
}, []);
|
||||
|
||||
const renderWeather = (location, weather) => {
|
||||
if (!weather) return <Text>{location}: Loading weather...</Text>;
|
||||
|
||||
const weatherInfo = weatherCodeMap[weather.weathercode] || { desc: 'Unknown', color: 'white' };
|
||||
|
||||
return (
|
||||
<Text>
|
||||
{location}: <Text color={weatherInfo.color}>{weatherInfo.desc}</Text>,{' '}
|
||||
<Text color="cyan">{weather.temperature}°C</Text> (Vent : {weather.windspeed} km/h)
|
||||
</Text>
|
||||
);
|
||||
};
|
||||
|
||||
const translateHomeAway = (homeAway) => {
|
||||
if (homeAway === 'Home') return 'domicile';
|
||||
if (homeAway === 'Away') return 'extérieur';
|
||||
return homeAway;
|
||||
};
|
||||
|
||||
return (
|
||||
<Box flexDirection="column" padding={1}>
|
||||
<Text>
|
||||
Hello, <Text color="green">{name}</Text> !
|
||||
</Text>
|
||||
<Text color="yellow">{formatDate(now)}</Text>
|
||||
<Text color="magenta">{formatTime(now)}</Text>
|
||||
{renderWeather('Nancy', weatherNancy)}
|
||||
{renderWeather('Paris', weatherParis)}
|
||||
|
||||
<Box marginTop={1} flexDirection="column">
|
||||
<Text color="red">Matches à venir de <Text color="red">SC Internacional</Text> :</Text>
|
||||
{!matchesInter && <Text>Chargement des matchs...</Text>}
|
||||
{matchesInter && matchesInter.length === 0 && <Text>Aucun match trouvé.</Text>}
|
||||
{matchesInter && matchesInter.slice(0, 2).map((m, i) => (
|
||||
<Text key={i}>
|
||||
{m.date} {m.time} - <Text color="red">SC Internacional</Text> vs {m.opponent} ({translateHomeAway(m.homeAway)})
|
||||
</Text>
|
||||
))}
|
||||
</Box>
|
||||
|
||||
<Box marginTop={1} flexDirection="column">
|
||||
<Text color="blue">Matches à venir de <Text color="blue">Paris FC</Text> :</Text>
|
||||
{!matchesParis && <Text>Chargement des matchs...</Text>}
|
||||
{matchesParis && matchesParis.length === 0 && <Text>Aucun match trouvé.</Text>}
|
||||
{matchesParis && matchesParis.slice(0, 2).map((m, i) => (
|
||||
<Text key={i}>
|
||||
{m.date} {m.time} - <Text color="blue">Paris FC</Text> vs {m.opponent} ({translateHomeAway(m.homeAway)})
|
||||
</Text>
|
||||
))}
|
||||
</Box>
|
||||
|
||||
<Text dimColor>Press Ctrl+C to exit.</Text>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user