0% found this document useful (0 votes)
3 views37 pages

Awesome/6 4 0/css/all Min Css

The document is an HTML template for a web application called AGRONOVA GX, focused on precision farming. It includes sections for real-time updates on weather, market prices, a farming calendar, and soil health monitoring, all styled with Tailwind CSS. The layout is designed to provide farmers with essential information in a user-friendly interface.

Uploaded by

mtongat64
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
3 views37 pages

Awesome/6 4 0/css/all Min Css

The document is an HTML template for a web application called AGRONOVA GX, focused on precision farming. It includes sections for real-time updates on weather, market prices, a farming calendar, and soil health monitoring, all styled with Tailwind CSS. The layout is designed to provide farmers with essential information in a user-friendly interface.

Uploaded by

mtongat64
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd

<!

DOCTYPE html>

<html lang=”en”>

<head>

<meta charset=”UTF-8” />

<meta name=”viewport” content=”width=device-width, initial-


scale=1.0” />

<title>AGRONOVA GX | Precision Farming</title>

<script src=[Link]

<link rel=”stylesheet” href=[Link]


awesome/6.4.0/css/[Link]>

<script>

[Link] = {

Theme: {

Extend: {

Colors: {

‘gx-teal’: ‘#2dd4bf’,

‘gx-amber’: ‘#f59e0b’,

‘gx-dark’: ‘#0f172a’,

‘gx-green’: ‘#10b981’,

},

Animation: {

‘pulse-slow’: ‘pulse 3s cubic-bezier(0.4, 0, 0.6, 1) infinite’,

</script>
<style>

@import url(‘[Link]
family=Inter:wght@300;400;500;600;700&display=swap’);

Body {

Background: linear-gradient(135deg, #0f172a, #020617);

Min-height: 100vh;

Font-family: ‘Inter’, sans-serif;

.bg-glass {

Background: rgba(15, 23, 42, 0.7);

Backdrop-filter: blur(12px);

Border: 1px solid rgba(45, 212, 191, 0.2);

.update-card {

Transition: all 0.3s ease;

.update-card:hover {

Transform: translateY(-4px);

Box-shadow: 0 10px 15px -3px rgba(13, 148, 136, 0.3);

.[Link] {

Background: #0d9488;

Color: white;

.[Link] {

Position: relative;
}

.[Link]::after {

Content: ‘’;

Position: absolute;

Bottom: 2px;

Left: 50%;

Transform: translateX(-50%);

Width: 4px;

Height: 4px;

Border-radius: 50%;

Background: #f59e0b;

.[Link] {

Color: #2dd4bf;

Background: rgba(45, 212, 191, 0.1);

Border-radius: 0.5rem;

.progress-bar {

Height: 6px;

Border-radius: 3px;

Background: rgba(255, 255, 255, 0.1);

Overflow: hidden;

.progress-fill {

Height: 100%;

Background: linear-gradient(90deg, #2dd4bf, #10b981);

Border-radius: 3px;
Transition: width 0.5s ease;

/* Modal styling (matches the app aesthetic) */

.modal-backdrop {

Position: fixed;

Inset: 0;

Background: rgba(2,6,23,0.6);

Display: flex;

Align-items: center;

Justify-content: center;

z-index: 60;

.modal {

Width: 90%;

Max-width: 420px;

Background: rgba(15,23,42,0.95);

Border: 1px solid rgba(45,212,191,0.12);

Padding: 1rem;

Border-radius: 0.75rem;

Color: #e6eef6;

Box-shadow: 0 10px 30px rgba(2,6,23,0.6);

.modal h3 { font-weight: 600; margin-bottom: 0.5rem; }

.modal label { font-size: 0.85rem; color: #cbd5e1; display: block; margin-


bottom: 0.25rem; }

.modal input[type=”text”] {
Width: 100%;

Padding: 0.5rem 0.6rem;

Background: rgba(255,255,255,0.03);

Border: 1px solid rgba(255,255,255,0.04);

Color: #e6eef6;

Border-radius: 0.5rem;

Margin-bottom: 0.5rem;

.modal .modal-actions {

Display:flex;

Gap:0.5rem;

Justify-content:flex-end;

Margin-top:0.5rem;

.btn {

Padding: 0.45rem 0.75rem;

Border-radius: 0.5rem;

Font-size: 0.9rem;

Cursor: pointer;

Border: none;

.btn-primary {

Background: #2dd4bf;

Color: #082226;

Font-weight: 600;

.btn-ghost {
Background: rgba(255,255,255,0.03);

Color: #e6eef6;

.event-color-dot {

Width: 14px;

Height: 14px;

Border-radius: 999px;

Display:inline-block;

Margin-right:0.5rem;

Vertical-align: middle;

Border: 1px solid rgba(255,255,255,0.05);

.events-list-small { display:flex; gap:0.5rem; flex-wrap:wrap; margin-


top:0.5rem; }

.events-chip {

Background: rgba(255,255,255,0.03);

Padding: 0.25rem 0.5rem;

Border-radius: 0.25rem;

Font-size: 0.8rem;

Display:flex;

Gap:0.4rem;

Align-items:center;

</style>

</head>

<body class=”flex flex-col items-center p-4 text-slate-100 font-sans pb-24”>

<!—Header with GX Logo 


<div class=”w-full max-w-md mb-6 bg-glass p-6 rounded-2xl shadow-lg
text-center”>

<div class=”flex flex-col items-center”>

<!—Animated SVG GX Logo 

<svg width=”80” height=”80” viewBox=”0 0 120 120” class=”mb-3


animate-pulse-slow”>

<defs>

<linearGradient id=”gxGradient” x1=”0%” y1=”0%” x2=”100%”


y2=”100%”>

<stop offset=”0%” stop-color=”#2dd4bf” />

<stop offset=”100%” stop-color=”#f59e0b” />

</linearGradient>

</defs>

<path d=”M60 15C85 15,105 35,105 60C105 85,85 105,60 105C35


105,15 85,15 60C15 35,35 15,60 15Z”

Fill=”none” stroke=”url(#gxGradient)” stroke-width=”8” stroke-


linejoin=”round”/>

<path d=”M40 40L80 40M50 50L70 50M40 60L80 60M50 70L70 70”

Stroke=”#0f172a” stroke-width=”3” stroke-linecap=”round”/>

</svg>

<h1 class=”text-3xl font-bold”>

<span class=”text-slate-100”>AGRO</span>

<span class=”text-gx-teal”>NOVA</span>

<span class=”text-gx-amber font-mono”>GX</span>

</h1>

<p class=”text-slate-300 text-sm mt-2”>Today: <span id=”current-date”


class=”font-medium”>Loading…</span></p>

</div>
</div>

<!—Real-Time Updates Section 

<div class=”w-full max-w-md space-y-4 mb-8”>

<!—Weather Card (live integration) 

<div class=”bg-glass update-card p-5 rounded-xl”>

<div class=”flex justify-between items-center mb-3”>

<h2 class=”text-lg font-semibold text-gx-teal flex items-center”>

<I class=”fas fa-cloud-sun mr-2 text-xl”></i>

Weather Update

</h2>

<div class=”flex items-center”>

<span id=”weather-location” class=”text-xs bg-slate-700 px-2 py-1


rounded mr-2”>Detecting…</span>

<I id=”refresh-weather” class=”fas fa-sync-alt text-xs text-slate-400


cursor-pointer hover:text-gx-teal”></i>

</div>

</div>

<div class=”flex items-center justify-between”>

<div class=”flex items-center”>

<div id=”weather-temp” class=”text-5xl font-light”>26°<span


class=”text-3xl”>C</span></div>

<I id=”weather-humidity” class=”fas fa-tint ml-4 text-blue-400 text-xl”


title=”Humidity: 65%”></i>

<I id=”weather-wind” class=”fas fa-wind ml-2 text-blue-300 text-xl”


title=”Wind: 12 km/h”></i>

</div>

<div class=”text-right”>
<p id=”weather-highlow” class=”text-sm”>H: 30° L: 18°</p>

<p id=”weather-desc” class=”text-sm text-slate-300”>Partly


Cloudy</p>

<p class=”text-xs mt-1”>Updated: <span id=”weather-time”>Just


now</span></p>

</div>

</div>

<div class=”mt-4”>

<div class=”progress-bar”>

<div id=”weather-rain” class=”progress-fill” style=”width:


65%”></div>

</div>

<div class=”flex justify-between text-xs mt-1”>

<span>Rain Probability</span>

<span id=”rain-text”>65%</span>

</div>

</div>

</div>

<!—Market Prices Card 

<div class=”bg-glass update-card p-5 rounded-xl”>

<div class=”flex justify-between items-center mb-3”>

<h2 class=”text-lg font-semibold text-gx-teal flex items-center”>

<I class=”fas fa-chart-line mr-2 text-xl”></i>

Market Prices

</h2>

<div class=”flex items-center”>


<span class=”text-xs bg-slate-700 px-2 py-1 rounded
mr-2”>Today</span>

<I class=”fas fa-ellipsis-v text-xs text-slate-400 cursor-pointer


hover:text-gx-teal”></i>

</div>

</div>

<div class=”space-y-3”>

<div class=”flex justify-between items-center text-sm”>

<div class=”flex items-center”>

<I class=”fas fa-seedling text-gx-green mr-2”></i>

<span>Maize (50kg)</span>

</div>

<div class=”flex items-center”>

<span class=”font-medium”>ZMW 320</span>

<I class=”fas fa-arrow-up text-xs text-green-400 ml-1”></i>

</div>

</div>

<div class=”flex justify-between items-center text-sm”>

<div class=”flex items-center”>

<I class=”fas fa-leaf text-amber-500 mr-2”></i>

<span>Soybeans (50kg)</span>

</div>

<div class=”flex items-center”>

<span class=”font-medium”>ZMW 480</span>

<I class=”fas fa-arrow-down text-xs text-red-400 ml-1”></i>

</div>

</div>
<div class=”flex justify-between items-center text-sm”>

<div class=”flex items-center”>

<I class=”fas fa-sun text-yellow-400 mr-2”></i>

<span>Sunflower (50kg)</span>

</div>

<div class=”flex items-center”>

<span class=”font-medium”>ZMW 410</span>

<I class=”fas fa-equals text-xs text-gray-400 ml-1”></i>

</div>

</div>

</div>

<p class=”text-xs mt-3 text-slate-300 flex items-center”>

<I class=”fas fa-database mr-1”></i> Source: Zambia National Farmers


Union (Updated hourly)

</p>

</div>

<!—Farming Calendar (dynamic, clickable) 

<div class=”bg-glass update-card p-5 rounded-xl”>

<div class=”flex justify-between items-center mb-3”>

<h2 class=”text-lg font-semibold text-gx-teal flex items-center”>

<I class=”fas fa-calendar-alt mr-2 text-xl”></i>

Farming Calendar

</h2>

<div>

<span id=”calendar-month-year” class=”text-xs bg-slate-700 px-2 py-


1 rounded”>Loading…</span>
</div>

</div>

<div class=”grid grid-cols-7 gap-1 mb-2 text-xs”>

<div class=”text-center py-1 text-slate-400”>Sun</div>

<div class=”text-center py-1 text-slate-400”>Mon</div>

<div class=”text-center py-1 text-slate-400”>Tue</div>

<div class=”text-center py-1 text-slate-400”>Wed</div>

<div class=”text-center py-1 text-slate-400”>Thu</div>

<div class=”text-center py-1 text-slate-400”>Fri</div>

<div class=”text-center py-1 text-slate-400”>Sat</div>

</div>

<div id=”calendar-days” class=”grid grid-cols-7 gap-1 text-sm”>

<!—JS injects day cells here 

</div>

<div class=”mt-4 space-y-2” id=”calendar-events-list”>

<!—Today / event summaries injected here 

</div>

</div>

<!—Soil Health Card (unchanged) 

<div class=”bg-glass update-card p-5 rounded-xl”>

<h2 class=”text-lg font-semibold text-gx-teal flex items-center mb-3”>

<I class=”fas fa-seedling mr-2 text-xl”></i>

Soil Health Monitoring

</h2>

<div class=”grid grid-cols-2 gap-4”>


<div class=”bg-slate-800 p-3 rounded-lg”>

<div class=”flex justify-between items-center mb-1”>

<span class=”text-xs text-slate-300”>Moisture</span>

<span class=”text-xs font-medium”>62%</span>

</div>

<div class=”progress-bar”>

<div class=”progress-fill” style=”width: 62%”></div>

</div>

</div>

<div class=”bg-slate-800 p-3 rounded-lg”>

<div class=”flex justify-between items-center mb-1”>

<span class=”text-xs text-slate-300”>Nitrogen</span>

<span class=”text-xs font-medium”>45%</span>

</div>

<div class=”progress-bar”>

<div class=”progress-fill” style=”width: 45%”></div>

</div>

</div>

<div class=”bg-slate-800 p-3 rounded-lg”>

<div class=”flex justify-between items-center mb-1”>

<span class=”text-xs text-slate-300”>pH Level</span>

<span class=”text-xs font-medium”>6.8</span>

</div>

<div class=”progress-bar”>

<div class=”progress-fill” style=”width: 68%”></div>

</div>

</div>
<div class=”bg-slate-800 p-3 rounded-lg”>

<div class=”flex justify-between items-center mb-1”>

<span class=”text-xs text-slate-300”>Organic Matter</span>

<span class=”text-xs font-medium”>3.2%</span>

</div>

<div class=”progress-bar”>

<div class=”progress-fill” style=”width: 32%”></div>

</div>

</div>

</div>

<button class=”w-full mt-4 bg-gx-teal text-gx-dark py-2 rounded-lg text-


sm font-medium hover:bg-opacity-90 transition”>

<I class=”fas fa-plus-circle mr-1”></i> Add Soil Test

</button>

</div>

</div>

<!—Bottom Navigation with GX Badge (unchanged) 

<div class=”fixed bottom-0 left-0 right-0 bg-slate-800 py-3 px-4 shadow-


2xl”>

<div class=”relative flex justify-around max-w-md mx-auto”>

<!—GX Edition Badge 

<div class=”absolute -top-3 left-1/2 transform -translate-x-1/2 bg-


gradient-to-r from-gx-teal to-gx-green text-white text-xs px-3 py-1 rounded-
full font-medium shadow-lg”>

<I class=”fas fa-bolt mr-1”></i> GX EDITION

</div>
<!—Nav Items 

<a href=”#” class=”flex flex-col items-center text-gx-teal p-2 rounded-lg


w-16 nav-item active”>

<I class=”fas fa-home text-xl”></i>

<span class=”text-xs mt-1”>Home</span>

</a>

<a href=”[Link]” class=”flex flex-col items-center text-slate-300 p-2


rounded-lg w-16 nav-item”>

<I class=”fas fa-bug text-xl”></i>

<span class=”text-xs mt-1”>Pests</span>

</a>

<a href=”[Link]” class=”flex flex-col items-center text-slate-300 p-


2 rounded-lg w-16 nav-item”>

<I class=”fas fa-shopping-basket text-xl”></i>

<span class=”text-xs mt-1”>Market</span>

</a>

<a href=”[Link]” class=”flex flex-col items-center text-slate-


300 p-2 rounded-lg w-16 nav-item”>

<I class=”fas fa-graduation-cap text-xl”></i>

<span class=”text-xs mt-1”>Learn</span>

</a>

<a href=”[Link]” class=”flex flex-col items-center text-slate-300 p-


2 rounded-lg w-16 nav-item”>

<I class=”fas fa-user text-xl”></i>

<span class=”text-xs mt-1”>Profile</span>

</a>

</div>

</div>
<!—Modal container (hidden by default) 

<div id=”modal-root” style=”display:none;”></div>

<script>

// Maintain original date display

Const options = { weekday: ‘long’, year: ‘numeric’, month: ‘long’, day:


‘numeric’ };

[Link](‘current-date’).textContent = new
Date().toLocaleDateString(‘en-ZM’, options);

// ---------------------------

// Weather integration

// ---------------------------

Const apiKey = “719ac96f5075d74b1d7955398c833b31”;

Let lastKnownCoords = null;

Let refreshIntervalId = null;

Function updateWeatherTime() {

Const now = new Date();

Const el = [Link](‘weather-time’);

If (el) [Link] = `${[Link]()}:$


{[Link]().toString().padStart(2, ‘0’)}`;

Async function fetchWeather(lat, lon) {

Try {

lastKnownCoords = { lat, lon };


const res = await
fetch(`[Link]
{lon}&units=metric&appid=${apiKey}`);

const data = await [Link]();

[Link](‘weather-temp’).innerHTML = `$
{[Link]([Link])}°<span class=”text-3xl”>C</span>`;

[Link](‘weather-location’).textContent = `$
{[Link]}, ${[Link]}`;

[Link](‘weather-humidity’).setAttribute(‘title’,
`Humidity: ${[Link]}%`);

[Link](‘weather-wind’).setAttribute(‘title’, `Wind: $
{[Link]} km/h`);

[Link](‘weather-highlow’).textContent = `H: $
{[Link]([Link].temp_max)}° L: $
{[Link]([Link].temp_min)}°`;

[Link](‘weather-desc’).textContent =
[Link][0].[Link](/\b\w/g, c => [Link]());

let rainProb = 0;

if ([Link] && [Link][“1h”]) {

rainProb = [Link](100, [Link]([Link][“1h”] * 20));

[Link](‘weather-rain’).[Link] = `${rainProb}
%`;

[Link](‘rain-text’).textContent = `${rainProb}%`;

updateWeatherTime();

} catch (err) {

[Link](‘Weather fetch error:’, err);


}

Async function detectLocationByIPAndFetch() {

Try {

Const r = await fetch(‘[Link]

Const loc = await [Link]();

If (loc && [Link] && [Link]) {

fetchWeather([Link], [Link]);

} else {

fetchWeather(-15.3875, 28.3228); // Lusaka fallback

} catch (err) {

[Link](‘IP detect failed, fallback to Lusaka’, err);

fetchWeather(-15.3875, 28.3228);

// Kick off quick IP detection

detectLocationByIPAndFetch();

if ([Link]) {

[Link](

pos => {

// fetch and set interval at 60s using the more accurate coords

fetchWeather([Link], [Link]);

if (refreshIntervalId) clearInterval(refreshIntervalId);
refreshIntervalId = setInterval(() => {

if (lastKnownCoords) fetchWeather([Link],
[Link]);

else detectLocationByIPAndFetch();

}, 60000);

},

Err => {

[Link](‘Geolocation denied/unavailable:’, err);

If (refreshIntervalId) clearInterval(refreshIntervalId);

refreshIntervalId = setInterval(() => detectLocationByIPAndFetch(),


60000);

);

} else {

refreshIntervalId = setInterval(() => detectLocationByIPAndFetch(),


60000);

[Link](‘refresh-weather’).addEventListener(‘click’, ()
=> {

If (lastKnownCoords) fetchWeather([Link],
[Link]);

Else detectLocationByIPAndFetch();

});

// ---------------------------

// Dynamic calendar + editable events (stored in localStorage)

// ---------------------------
(function calendarModule() {

Const calendarDaysEl = [Link](‘calendar-days’);

Const monthYearEl = [Link](‘calendar-month-year’);

Const eventsListEl = [Link](‘calendar-events-list’);

Const modalRoot = [Link](‘modal-root’);

// Annual events (repeat each year); month numbers are 1-12

Const defaultAnnualEvents = [

{ id: ‘soil-prep’, title: ‘Soil Preparation Day’, month: 8, day: 10, color:
‘#14b8a6’ }, // Aug 10

{ id: ‘maize-window’, title: ‘Maize Planting Window’, month: 7, dayStart:


10, dayEnd: 15, color: ‘#f59e0b’ } // Jul 10-15

];

// Storage key

Const STORAGE_KEY = ‘agronova_calendar_events_v1’;

// Load stored events, merge with defaults if not present

Function loadEvents() {

Const raw = [Link](STORAGE_KEY);

Let stored = raw ? [Link](raw) : {};

// stored: { “YYYY-MM-DD”: [{id, title, color}] }

// ensure defaults exist for current year (annual events)

Return stored || {};

Function saveEvents(obj) {
[Link](STORAGE_KEY, [Link](obj));

// Helper: date key YYYY-MM-DD

Function dateKey(year, monthIndex, day) {

Const mm = String(monthIndex + 1).padStart(2, ‘0’);

Const dd = String(day).padStart(2, ‘0’);

Return `${year}-${mm}-${dd}`;

// Add event to a specific date

Function addEventToDate(year, monthIndex, day, eventObj) {

Const key = dateKey(year, monthIndex, day);

Const evs = events[key] || [];

[Link](eventObj);

Events[key] = evs;

saveEvents(events);

// Remove a single event by index from date

Function removeEventFromDate(year, monthIndex, day, index) {

Const key = dateKey(year, monthIndex, day);

If (!events[key]) return;

Events[key].splice(index, 1);

If (events[key].length === 0) delete events[key];

saveEvents(events);

}
// Merge default annual events into UI without overwriting user changes.

// Defaults are not saved to localStorage as fixed entries; we show them


if no user event exists.

Function getEventsForDate(year, monthIndex, day) {

Const key = dateKey(year, monthIndex, day);

Const out = [];

// user events

If (events[key]) {

For (const e of events[key]) [Link]€;

// defaults if applicable

For (const def of defaultAnnualEvents) {

If ([Link] && [Link] – 1 === monthIndex && [Link] === day) {

// ensure not duplicated if user created identical event (we don’t de-
dup aggressively)

[Link]({ id: [Link], title: [Link], color: [Link], isDefault: true });

} else if ([Link] && [Link] && [Link] – 1 ===


monthIndex && day >= [Link] && day <= [Link]) {

[Link]({ id: [Link], title: [Link], color: [Link], isDefault: true });

Return out;

// Render month function

Function renderMonth(year, monthIndex) {

[Link] = ‘’;
[Link] = ‘’;

const firstDay = new Date(year, monthIndex, 1);

const startWeekday = [Link](); // 0-6

const daysInMonth = new Date(year, monthIndex + 1, 0).getDate();

// leading prev-month muted days

For (let I = 0; I < startWeekday; i++) {

Const dayNum = new Date(year, monthIndex, 0).getDate() –


(startWeekday – 1) + I;

Const div = [Link](‘div’);

[Link] = ‘text-center py-1 text-slate-400’;

[Link] = dayNum;

[Link](div);

Const today = new Date();

Const tY = [Link](), tM = [Link](), tD =


[Link]();

For (let d = 1; d <= daysInMonth; d++) {

Const div = [Link](‘div’);

[Link] = ‘text-center py-1 calendar-day’;

[Link] = d;

const evs = getEventsForDate(year, monthIndex, d);

if ([Link] > 0) [Link](‘event’);


if (year === tY && monthIndex === tM && d === tD) {

[Link](‘active’);

// small events chips display inside day cell (small)

If ([Link] > 0) {

Const chips = [Link](‘div’);

[Link] = ‘events-list-small mt-1 justify-center’;

[Link](0, 2).forEach(ev => {

Const chip = [Link](‘div’);

[Link] = ‘events-chip’;

Const dot = [Link](‘span’);

[Link] = ‘event-color-dot’;

[Link] = [Link] || ‘#f59e0b’;

[Link](dot);

Const t = [Link](‘span’);

[Link] = [Link] > 12 ? [Link](0, 11) + ‘…’ :


[Link];

[Link](t);

[Link](chip);

});

[Link](chips);

// click handler to open modal for this day

(function(year, monthIndex, d) {
[Link](‘click’, () => openDayModal(year, monthIndex,
d));

})(new Date(year, monthIndex).getFullYear(), monthIndex, d);

[Link](div);

// trailing next-month muted days fill to multiple of 7

Const totalCells = startWeekday + daysInMonth;

Const nextFill = (7 – (totalCells % 7)) % 7;

For (let n = 1; n <= nextFill; n++) {

Const div = [Link](‘div’);

[Link] = ‘text-center py-1 text-slate-400’;

[Link] = n;

[Link](div);

// update header

Const monthNames = [

‘January’,’February’,’March’,’April’,’May’,’June’,

‘July’,’August’,’September’,’October’,’November’,’December’

];

[Link] = `${monthNames[monthIndex]} ${year}`;

// Build event summaries for the month (includes defaults & user
events)

buildEventsSummary(year, monthIndex);
}

Function buildEventsSummary(year, monthIndex) {

[Link] = ‘’;

const monthNames = [

‘January’,’February’,’March’,’April’,’May’,’June’,

‘July’,’August’,’September’,’October’,’November’,’December’

];

// Find default events in this month

[Link](ev => {

if ([Link] && [Link] – 1 === monthIndex) {

[Link](createEventSummary([Link], `$
{monthNames[[Link]-1]} ${[Link]}`, [Link]));

} else if ([Link] && [Link] && [Link] – 1 ===


monthIndex) {

[Link](createEventSummary([Link], `$
{monthNames[[Link]-1]} ${[Link]}-${[Link]}`, [Link]));

});

// Also show user events that fall in this month

[Link](events).forEach(key => {

// key format YYYY-MM-DD

Const [y, m, d] = [Link](‘-‘).map(Number);

If (y === year && (m – 1) === monthIndex) {

Const evs = events[key];

[Link](ev => {
[Link](createEventSummary([Link], `${year}-$
{String(m).padStart(2,’0’)}-${String(d).padStart(2,’0’)}`, [Link]));

});

});

// Show today’s box if today’s date has any events (default or user)

Const now = new Date();

Const todays = getEventsForDate([Link](), [Link](),


[Link]());

If ([Link] > 0) {

Const todayBox = createTodayBox(todays);

[Link](todayBox, [Link]);

} else {

// Original UI had a “Today: Soil Preparation Day” static message — we


display today’s date as neutral

Const neutral = [Link](‘div’);

[Link] = ‘flex items-center text-sm p-2 bg-slate-800


rounded-lg’;

Const dot = [Link](‘div’);

[Link] = ‘w-2 h-2 bg-teal-500 rounded-full mr-2’;

[Link](dot);

Const span = [Link](‘span’);

[Link] = `Today: ${[Link](undefined,


{ month: ‘long’, day: ‘numeric’ })}`;

[Link](span);

Const icon = [Link](‘I’);

[Link] = ‘fas fa-bell ml-auto text-xs text-gx-amber’;


[Link](icon);

[Link](neutral, [Link]);

Function createEventSummary(title, subtitle, color) {

Const wrapper = [Link](‘div’);

[Link] = ‘flex items-center text-sm p-2 bg-slate-800


rounded-lg’;

Const dot = [Link](‘div’);

[Link] = ‘w-2 h-2 rounded-full mr-2’;

[Link] = color || ‘#14b8a6’;

[Link](dot);

Const span = [Link](‘span’);

[Link] = `${title} — ${subtitle}`;

[Link](span);

Const icon = [Link](‘I’);

[Link] = ‘fas fa-clock ml-auto text-xs text-slate-400’;

[Link](icon);

Return wrapper;

Function createTodayBox(evList) {

Const container = [Link](‘div’);

[Link] = ‘flex items-center text-sm p-2 bg-slate-800


rounded-lg’;

Const dot = [Link](‘div’);


[Link] = ‘w-2 h-2 bg-teal-500 rounded-full mr-2’;

[Link](dot);

Const span = [Link](‘span’);

[Link] = [Link](e => [Link]).join(‘, ‘);

[Link](span);

Const bell = [Link](‘I’);

[Link] = ‘fas fa-bell ml-auto text-xs text-gx-amber’;

[Link](bell);

Return container;

// Modal utilities

Function openModal(contentHtml) {

[Link] = ‘’;

const backdrop = [Link](‘div’);

[Link] = ‘modal-backdrop’;

const modal = [Link](‘div’);

[Link] = ‘modal’;

[Link] = contentHtml;

[Link](modal);

[Link](backdrop);

[Link] = ‘block’;

// close on backdrop click (outside modal)

[Link](‘click’, € => {

If ([Link] === backdrop) closeModal();

});
}

Function closeModal() {

[Link] = ‘none’;

[Link] = ‘’;

// Modal for a day: list events (if any) and form to add new event

Function openDayModal(year, monthIndex, day) {

Const key = dateKey(year, monthIndex, day);

Const currentEvents = events[key] ? events[key].slice() : [];

// Include default annual events for UI display, but careful not to allow
removing default events unless user removes by adding a custom event to
override (we will allow user to remove visible default by explicitly “Hide
default” action)

Const defaults = [];

[Link](def => {

if ([Link] && [Link] – 1 === monthIndex && [Link] === day)


[Link]({ title: [Link], color: [Link], isDefault: true, defId: [Link] });

if ([Link] && [Link] && [Link] – 1 === monthIndex &&


day >= [Link] && day <= [Link]) [Link]({ title: [Link],
color: [Link], isDefault: true, defId: [Link] });

});

// Build modal content

Let html = `<h3>Events for


${monthIndex+1}/${day}/${year}</h3>`;

Html += `<div id=”modal-existing-events” style=”max-height:200px;


overflow:auto; margin-top:0.5rem;”>`;

If ([Link] === 0 && [Link] === 0) {


Html += `<div style=”color:#cbd5e1; font-size:0.9rem;”>No events
for this day.</div>`;

} else {

// user events

[Link]((ev, idx) => {

html += `<div class=”flex items-center justify-between”


style=”margin-top:0.35rem;”>` +

`<div style=”display:flex;align-items:center;”><span
class=”event-color-dot” style=”background:${[Link] ||
‘#f59e0b’}”></span><span
style=”font-size:0.95rem”>${[Link]}</span></div>` +

`<div><button data-ev-index=”${idx}” class=”btn btn-ghost


modal-remove-btn” style=”padding:0.25rem
0.4rem;”>Remove</button></div>` +

`</div>`;

});

// default events (showed, allow “hide default” to insert a marker in


localStorage that hides it)

[Link]((dev, idx) => {

// Check if default is hidden in storage (we implement a hideDefault


map stored separately)

Html += `<div class=”flex items-center justify-between”


style=”margin-top:0.35rem;”>` +

`<div style=”display:flex;align-items:center;”><span
class=”event-color-dot” style=”background:${[Link]}”></span><span
style=”font-size:0.95rem”>${[Link]} (default)</span></div>` +

`<div><button data-def-id=”${[Link]}” class=”btn btn-


ghost modal-hide-default-btn” style=”padding:0.25rem
0.4rem;”>Hide</button></div>` +

`</div>`;

});
}

Html += `</div>`;

// add new event form

Html += `<div style=”margin-top:0.6rem;”>` +

`<label>Event title</label>` +

`<input id=”modal-event-title” type=”text” placeholder=”e.g. Soil


test” />` +

`<label>Color</label>` +

`<div style=”display:flex; gap:0.5rem; margin-top:0.25rem;”>` +

`<button data-color=”#14b8a6” class=”color-btn btn btn-ghost”


title=”Teal”><span class=”event-color-dot”
style=”background:#14b8a6”></span></button>` +

`<button data-color=”#f59e0b” class=”color-btn btn btn-ghost”


title=”Amber”><span class=”event-color-dot”
style=”background:#f59e0b”></span></button>` +

`<button data-color=”#60a5fa” class=”color-btn btn btn-ghost”


title=”Blue”><span class=”event-color-dot”
style=”background:#60a5fa”></span></button>` +

`<button data-color=”#ef4444” class=”color-btn btn btn-ghost”


title=”Red”><span class=”event-color-dot”
style=”background:#ef4444”></span></button>` +

`</div>` +

`</div>`;

Html += `<div class=”modal-actions” style=”margin-top:0.6rem;”>` +

`<button id=”modal-cancel” class=”btn


btn-ghost”>Cancel</button>` +

`<button id=”modal-add” class=”btn btn-primary”>Add


Event</button>` +
`</div>`;

openModal(html);

// Wire up modal buttons

[Link](‘modal-cancel’).addEventListener(‘click’,
closeModal);

// color selection

Let chosenColor = ‘#14b8a6’;

[Link](‘.color-btn’).forEach(btn => {

[Link](‘click’, € => {

[Link]();

chosenColor = [Link](‘data-color’);

// highlight selected visually (small)

[Link](‘.color-btn’).forEach(b => [Link]


= ‘0.6’);

[Link] = ‘1’;

});

});

// add event

[Link](‘modal-add’).addEventListener(‘click’, () =>
{

Const titleInput = [Link](‘#modal-event-title’);

Const title = [Link] && [Link]();

If (!title) {

[Link]();
return;

// create event object

Const evObj = { id: ‘u-‘ + [Link](), title, color: chosenColor };

addEventToDate(year, monthIndex, day, evObj);

closeModal();

// re-render month to show the new event

renderMonth(year, monthIndex);

});

// remove user events buttons

[Link](‘.modal-remove-btn’).forEach(b => {

[Link](‘click’, () => {

const idx = parseInt([Link](‘data-ev-index’), 10);

removeEventFromDate(year, monthIndex, day, idx);

closeModal();

renderMonth(year, monthIndex);

});

});

// hide default event (store hidden defaults map)

[Link](‘.modal-hide-default-btn’).forEach(b => {

[Link](‘click’, () => {

const defId = [Link](‘data-def-id’);

// Mark default as hidden for this date by storing a stub event with
special flag
// Implementation: savedHiddenDefaults is an object keyed by defId
and keyed by date

Const hiddenKey = ‘agronova_hidden_defaults_v1’;

Const raw = [Link](hiddenKey);

Let hidden = raw ? [Link](raw) : {};

Const date = dateKey(year, monthIndex, day);

Hidden[date] = hidden[date] || [];

If (!hidden[date].includes(defId)) hidden[date].push(defId);

[Link](hiddenKey, [Link](hidden));

closeModal();

renderMonth(year, monthIndex);

});

});

// global events store

Const events = loadEvents();

// tweak getEventsForDate to respect hidden defaults

Const hiddenDefaultsKey = ‘agronova_hidden_defaults_v1’;

Function getHiddenDefaultsForDate(year, monthIndex, day) {

Const raw = [Link](hiddenDefaultsKey);

If (!raw) return [];

Const hidden = [Link](raw);

Const k = dateKey(year, monthIndex, day);

Return hidden[k] || [];

}
// override previous getEventsForDate (redefine)

Function getEventsForDate(year, monthIndex, day) {

Const key = dateKey(year, monthIndex, day);

Const out = [];

// user events

If (events[key]) {

For (const e of events[key]) [Link]€;

// defaults if applicable and not hidden

Const hidden = getHiddenDefaultsForDate(year, monthIndex, day);

For (const def of defaultAnnualEvents) {

If ([Link] && [Link] – 1 === monthIndex && [Link] === day) {

If (![Link]([Link])) [Link]({ id: [Link], title: [Link], color:


[Link], isDefault: true });

} else if ([Link] && [Link] && [Link] – 1 ===


monthIndex && day >= [Link] && day <= [Link]) {

If (![Link]([Link])) [Link]({ id: [Link], title: [Link], color:


[Link], isDefault: true });

Return out;

// expose some functions to outer scope if needed (not necessary)

// initialize to current month

Const now = new Date();

renderMonth([Link](), [Link]());
// allow navigation later (not requested, but keep hooks if wanted)

// e.g., you could add prev/next month buttons and call renderMonth
accordingly

})();

// keep original click effect for update-card

[Link](‘.update-card’).forEach(card => {

[Link](‘click’, function() {

[Link] = ‘translateY(-2px)’;

setTimeout(() => {

[Link] = ‘’;

}, 200);

});

});

// Stop pulse animation after load (unchanged)

setTimeout(() => {

[Link](‘svg’).[Link](‘animate-pulse-slow’);

}, 2000);

</script>

</body>

</html>

You might also like