);
}
function WeekendActivityPlan({ historyItems }) {
const { generate, loading, error } = useAI();
const [plan, setPlan] = useState(null);
const [planLoading, setPlanLoading] = useState(false);
const [planError, setPlanError] = useState('');
const [refreshKey, setRefreshKey] = useState(0);
const historySummary = useMemo(() => {
const weatherCounts = new Map();
const activityCounts = new Map();
historyItems.forEach((item) => {
const weather = String(item?.weatherType || item?.weather_type || item?.weather || 'Unknown');
const activity = String(item?.activityType || item?.activity_type || item?.activity || item?.title || 'Activity');
weatherCounts.set(weather, (weatherCounts.get(weather) || 0) + 1);
activityCounts.set(activity, (activityCounts.get(activity) || 0) + 1);
});
return {
total: historyItems.length,
topWeather: Array.from(weatherCounts.entries()).sort((a, b) => b[1] - a[1]).slice(0, 3),
topActivities: Array.from(activityCounts.entries()).sort((a, b) => b[1] - a[1]).slice(0, 5),
};
}, [historyItems]);
useEffect(() => {
let cancelled = false;
async function buildPlan() {
setPlanLoading(true);
setPlanError('');
try {
const system = 'You are an expert weekend activity planner. Create concise, personalized Saturday and Sunday activity suggestions using weather forecast and user history. Return valid JSON only.';
const userPrompt = JSON.stringify({
request: 'Generate a personalized weekend activity plan for Saturday and Sunday.',
userHistory: historySummary,
weatherForecast: 'Use the current forecast data available in the app context to recommend weather-appropriate activities.',
instructions: [
'Include a title, short overview, Saturday plan, Sunday plan, and 3 quick tips.',
'Base recommendations on the user\'s past preferences from history items.',
'Make the plan practical, upbeat, and specific to the forecast.',
'Return JSON with keys: title, overview, saturday, sunday, tips.',
'For saturday and sunday, include keys: weatherFit, morning, afternoon, evening.',
'For tips, return an array of 3 strings.'
],
});
const result = await generate({ system, user: userPrompt, json: true });
if (!cancelled && result) {
setPlan(result);
}
} catch (err) {
if (!cancelled) {
setPlanError('Could not generate a weekend plan right now.');
}
} finally {
if (!cancelled) {
setPlanLoading(false);
}
}
}
buildPlan();
return () => {
cancelled = true;
};
}, [generate, refreshKey, historySummary]);
const fallbackTips = [
'Try activities that match the best weather window.',
'Use your most common activity types as a starting point.',
'Keep one flexible indoor backup plan ready.'
];
return (
AI Weekend Plan
Personalized Saturday and Sunday ideas based on your forecast and activity history.
{planLoading || loading ? (
๐ค
Generating your weekend plan...
Analyzing your activity history and the forecast to tailor suggestions.
) : planError || error ? (
โ ๏ธ
Weekend plan unavailable
{planError || 'AI planning is temporarily unavailable.'}
) : (
AI Personalized
{plan?.title || 'Your Weekend Activity Plan'}
{plan?.overview || 'A weekend plan tailored to the weather forecast and your most common activity preferences.'}
Your recent patterns
{historySummary.total > 0
? `Top weather match: ${historySummary.topWeather[0]?.[0] || 'Unknown'} ยท Favorite activities: ${historySummary.topActivities.map((item) => item[0]).join(', ')}`
: 'No activity history yet, so this plan uses the forecast with general weekend suggestions.'}
Saturday
{plan?.saturday?.weatherFit || 'Weather-fit recommendations for Saturday.'}
Morning: {plan?.saturday?.morning || 'Start with a flexible morning activity.'}
Afternoon: {plan?.saturday?.afternoon || 'Choose an activity that matches the best weather window.'}
Evening: {plan?.saturday?.evening || 'Wind down with a low-effort evening plan.'}
Sunday
{plan?.sunday?.weatherFit || 'Weather-fit recommendations for Sunday.'}
Morning: {plan?.sunday?.morning || 'Start the day with one of your favorite activity types.'}
Afternoon: {plan?.sunday?.afternoon || 'Use the forecast to pick an outdoor or indoor backup.'}
Evening: {plan?.sunday?.evening || 'End with something restorative and simple.'}