Commit Graph

60 Commits

Author SHA1 Message Date
0d942c51db refactor: simplify break threshold picker values and labels 2026-06-24 21:06:23 +03:30
5f12e3838b feat: add break threshold picker UI to settings with preset values
Replaces the text-only instructions with a grid of common break thresholds (0/5/10/15/30 min, 1/2/4/8h) matching the accent picker pattern.
2026-06-24 20:59:49 +03:30
e399c3ee88 feat: add break threshold to settings UI with inline button and callback 2026-06-24 20:58:18 +03:30
c9dd076235 fix: count work hours in summary even on day-off days
buildMonthlySummary now includes hours for days marked as day-off, matching buildStatusText behavior. Shows "Xh worked (Day Off)" when a day-off day has events.
2026-06-24 20:53:15 +03:30
e539350030 refactor: simplify calendar nav buttons by removing redundant year/step numbers 2026-06-24 20:49:07 +03:30
834c318271 feat: add /summary, /setbreak, weekly totals, and fix command dispatch for arg-bearing commands
- Add /summary [YYYY-MM] command for monthly work/break/day-off totals

- Add weekly totals row to main menu status

- Add /setbreak <minutes> for configurable daily break threshold

- Fix HandleMessage routing: extract command name instead of exact match (fixes /export YYYY-MM, /edit, /note, /summary, /setbreak)

- Update README with full command table and configurable break docs
2026-06-24 20:39:51 +03:30
323c1bc010 test: add dateutil and totals tests for calendar conversions and ComputeDailyTotals 2026-06-24 20:07:38 +03:30
e7e4dc7bfe fix: unsilence all error returns from SQL Exec, Bot API calls, and migrations 2026-06-24 20:03:24 +03:30
4165839477 feat: add event notes with pending state, 5-min TTL, cancel, and /note command 2026-06-24 19:49:32 +03:30
68c8518522 add year navigation: year row at top of calendar, clickable year in export, shared buildYearPicker with 12-year grid 2026-06-24 19:47:03 +03:30
8d919decb0 export: tint day-off rows with theme totalFill background 2026-06-24 19:23:16 +03:30
4edff71bfd replace manual SQL migration with goose (v3); embed migrations in binary; remove schema.sql / SCHEMA_PATH 2026-06-24 19:20:48 +03:30
c959cb7a87 export: include all days, show Day Off in type column; menu: don't hide status on day off 2026-06-24 19:06:54 +03:30
af7a438174 feat: extended the build minute keyboard to have each 10 minutes from 0 to 50 2026-06-24 15:06:08 +03:30
353056349f DRY hour/minute picker: extract shared buildHourPickerKeyboard/buildMinutePickerKeyboard 2026-06-24 15:04:22 +03:30
75da4648aa feat: add IN/OUT event creation from day view in history
- Empty day view now shows Add IN / Add OUT buttons
- Day view with events also shows Add IN / Add OUT below existing events
- Hour picker → minute picker (15-min intervals) → event creation flow
- Back button returns to the day view
2026-06-24 15:02:08 +03:30
49c0e82bac refactor: migrate from go-telegram-bot-api/v5 to go-telegram/bot
- Replaced tgbotapi with go-telegram/bot (zero-dependency, context-aware, Bot API 10.0)
- All handler methods now accept context.Context; threading ctx through all sends/edits
- Changed from function-based (NewMessage/NewEditMessageText/NewInlineKeyboardMarkup) to struct-param API (SendMessageParams/EditMessageTextParams/InlineKeyboardMarkup)
- Added colored buttons: DEL buttons in calendar use Style: 'danger' (red)
- Both polling and webhook modes preserved with new library patterns
- Context-based shutdown (signal.NotifyContext) replaces stop channel
2026-06-24 14:56:50 +03:30
fb2d0ef7d1 chore: changed the rate limit down to 1 second instead of 2 2026-06-24 11:39:47 +03:30
a8b849f8fd refactor: split handlers.go into 5 files, redesign export month picker, pad calendar rows, improve comments
- Split 1571-line handlers.go into: handlers.go (core), clock.go, settings.go, calendar.go, report.go
- Redesigned export month picker: year navigation + 12-month grid instead of prev/next month
- Fixed calendar last row: pad remaining cells with empty buttons to ensure 7 columns
- Added Go doc comments across all files (dateutil.go, totals.go, store.go, main.go, webhook.go)
2026-06-24 11:33:17 +03:30
d8599657f4 refactor: export full Gregorian range, add timezone fallback, cleanup rate limit, configurable schema path
- GenerateMonthlyReport now takes explicit Gregorian start/end range,
  computed via monthGregorianRange, so Jalali/Hijri months spanning
  two Gregorian months are fully covered in exports.
- Added loadLocation helper (UTC fallback on error) and replaced all
  11 ignored-error call sites in handlers + export.
- Added periodicCleanup goroutine in NewHandler to prevent unbounded
  growth of the rateLimit map.
- schemaPath is now read from SCHEMA_PATH env var (init), defaulting
  to /app/db/schema.sql.
- Migrated sendDayView to use sendOrEdit helper, removing duplicated
  send/edit branching.
- Removed dead code: userYearMonthToGregorian (unused), the old
  startOffset function (replaced).
- Updated README with calendar docs, new env vars, full project tree.
- Updated .env.example and docker-compose.yml with SCHEMA_PATH.
- Simplified Makefile: added fmt, tidy, check, run-dev targets;
  removed broken Make-glob prerequisite pattern.
2026-06-24 11:21:54 +03:30
f89f5607aa fix: calendar day-of-week offset off by one, nav double-jump, race conditions
- Fix Jalali/Gregorian/Hijri day-of-week startOffset formulas
  (dow returns 0=Sat, not 0=Sun as the old comment claimed)
- Fix calendar and export month picker navigation jumping 2 months
  (navMonth buttons already have pre-computed values; handlers
  were decrementing/incrementing them again)
- Fix GetOrCreateUser/GetOrCreateDay race condition with INSERT OR IGNORE
- Add month/day bounds validation in handleEditMsg to prevent panic
2026-06-24 11:07:53 +03:30
577aee91fb refactor: remove dead code, DRY calendar navigation and helpers
- Fix Jalali calendar weekday offset in buildCalendarMonth
- Remove unused gregorianDateKey function and PairCount field
- Replace inline export month title with formatMonthTitle
- Extract navMonth helper for prev/next month navigation
- Extract sendOrEdit helper for send-vs-edit message pattern
- Extract monthGregorianRange helper to simplify editCalendar 3-way switch
- Replace export displayDate conversion with formatDateForCalendar
2026-06-24 10:54:06 +03:30
67eae5ffa3 fix export timezone and calendar month title
- Export now uses time.Now().In(loc) for year/month so users in
  positive UTC offsets get the correct month
- Export month title for Jalali/Hijri now correctly converts the
  first day of the Gregorian month to the target calendar instead
  of using the Gregorian month index to look up target month names
2026-06-24 10:32:17 +03:30
8fe43bff4d add settimezone command and timezone display in settings
- New /settimezone <IANA name> command to change user timezone
- Shows current timezone in settings menu
- timezone callback shows current value and instructions
- Updated /help with the new command
2026-06-24 10:17:09 +03:30
069bbb614e convert calendar day view header to user's calendar type 2026-06-24 10:14:09 +03:30
cafa139198 add /help command 2026-06-24 10:11:18 +03:30
69c5e20d8e display date in user's selected calendar on main menu and reports
buildStatusText and buildDailyReport now use formatDateForCalendar
to convert the stored Gregorian date to the user's calendar type
(jalali/hijri/gregorian).
2026-06-24 10:06:39 +03:30
07306cb0f0 remove reply keyboard; keep Clock In/Out as inline buttons only
- Removed smartKeyboard, defaultKeyboard, updateReplyKeyboard
- Removed statusMsg/keyboardMsg tracking from Handler
- sendText now sends plain messages (no reply keyboard)
- handleActionMsg sends result with mainKeyboard() inline keyboard
- handleActionCallback edits message with backKeyboard (unchanged)
- handleStart sends welcome + menu with mainKeyboard
- SendDailyReport sends plain text report
- Removed text-trigger 'Clock In'/'Clock Out' message handlers
  (only /clockin and /clockout commands remain)
2026-06-24 10:00:27 +03:30
9c83ed98c6 fix: keep keyboard update message alive instead of send-delete pattern
Previous approach (send \u200C then immediately delete it) lost the
reply keyboard because Telegram may not persist the keyboard from a
deleted message. Now we delete the OLD keyboard message and keep the
new one, ensuring the reply keyboard is always present and correct.
2026-06-24 09:52:28 +03:30
b6c7cf81c8 fix: prefix calendar type callbacks with caltype_ to avoid conflict with cal_day/cal_prev/cal_next
Routes caltype_gregorian/jalali/hijri to selectCalendar and
cal_day/cal_prev/cal_next to handleHistoryCallback as intended.
2026-06-24 09:50:28 +03:30
b900710196 fix: correct Jalali calendar year conversion
Complete rewrite of gregorianToJalali and jalaliToGregorian using
proper JDN arithmetic. Removed broken epoch offset (226899 / year 979)
and replaced with jalaliEpochJDN = 1948320 (March 21, 622 CE).

Verified: 2026-06-24 -> Jalali 1405-04-03 (correct)
Nowruz 1405 verified as 2026-03-21
2026-06-24 09:48:39 +03:30
9d123316e6 feat: Hijri calendar, virtual midnight crossover, overlap rejection, WAL mode
- Hijri (قمری) calendar added as 3rd calendar option with tabular conversion
- Calendar type select menu (like accent) with gregorian/jalali/hijri
- Calendar type applied to exports and reports
- Midnight crossover: virtual splits at computation time (no synthetic DB events)
  - Handles both UTC and local timezone boundaries
  - Timezone changes handled naturally (recomputed on-the-fly)
- Rate limiting per user ID instead of chat ID
- WAL mode enabled for SQLite
- Smart reply keyboard updates after every state change
- Overlapping time edits rejected (must preserve in/out alternation)
- Single event deletion warns if timeline needs repair
- Day off no longer prevents clock in/out
- Accent colors shown with descriptive names in select menu
- Delete button label changed to DEL for visual distinction
2026-06-24 09:39:15 +03:30
6f6cc6f184 feat: midnight crossover, rate limit, smart keyboard, status menu, settings
- Midnight crossover: auto-close previous day session on clock-in
- Rate limiting: 2s cooldown per chat_id in both messages and callbacks
- Smart reply keyboard: single button changes to Clock In/Out based on state
- Status info on main menu shows: date, work type, working status, today's total
- Settings sub-menu with inline buttons for accent, report toggle, report time
- Accent selection inline keyboard with > indicator and back button
- Notes displayed in daily report (e.g. 'auto midnight')
- Back buttons on all sub-menus (work type, accent, settings)
- Settings button added to main menu
2026-06-24 07:56:04 +03:30
2970b7d3fc feat: redesigned DB schema with users, work_types, days, events 2026-06-24 00:36:16 +03:30
8616ed0867 feat: multi-user isolation and graceful shutdown
- Add chat_id to events, settings, and days_off for per-user data
- Add proper graceful shutdown (signal handling, WaitGroup)
- Separate polling and webhook modes with goroutine management
- Add schema migration from single-user to multi-user schema
- Refactor handlers with shared actionFunc pattern (msg + callback)
- Fix schema path for Docker deployment (/app/db/schema.sql)
- Remove emoji from output text for cleaner formatting
2026-06-24 00:14:41 +03:30
7aada8d118 Add README.md
Some checks failed
CI / build (push) Has been cancelled
2026-06-23 22:36:41 +03:30
b4fab29d45 Clean up: remove unused packages, switch to slog, tidy Makefile 2026-06-23 22:34:01 +03:30
32446a99d1 Fix break tracking (out→in gap), add startup log, clean up /start message 2026-06-23 22:00:25 +03:30
7da6f4cb49 Add BOT_ALLOWED_USERS, fix SetColWidth params, drop fmt import, save chat_id on start 2026-06-23 21:56:18 +03:30
a92c72f46a feat: add persistent reply keyboard with Clock In / Clock Out buttons
Also handle button text (English + Persian) in message router.
2026-06-23 21:44:41 +03:30
5009bb130c chore: remove AGENTS.md (all tasks implemented) 2026-06-23 21:42:55 +03:30
4a5778afe5 feat: add inline keyboard, /start command, and callback handlers
- Show main menu with Clock In/Out, Report, Export, Remote, Day Off buttons
- Each action result includes a 'Back to Menu' button
- Handle callback queries alongside text commands
- Delete stale webhook before switching to polling
- Log i18n initialization error instead of silently ignoring it
2026-06-23 21:42:52 +03:30
0be03f7078 chore: connect bot container to proxy_net for nginx reverse-proxy
This allows nginx-edge to reach the bot via service name
on the shared proxy_net external network.
2026-06-23 21:42:45 +03:30
c4e8c8dc3a fix: make schema idempotent with IF NOT EXISTS
Add i18n locale files to Docker image and fix all CREATE
statements to use IF NOT EXISTS to survive container restarts.
2026-06-23 21:42:39 +03:30
b0fcb7a6c3 main: pass correct APIEndpoint to NewBotAPIWithClient 2026-06-23 21:00:27 +03:30
3aaf5b326d main: use default HTTP client (proxy via env) 2026-06-23 20:58:52 +03:30
f6d6e994aa Docker: proxy args for go mod download (temporary) 2026-06-23 20:53:58 +03:30
7d03a4d8fc Docker: use explicit Go 1.26.4 image to match go.mod 2026-06-23 20:52:52 +03:30
0a9175add4 handlers: replace fmt.Errorf with errors.New to satisfy vet
All checks were successful
CI / build (push) Successful in 55s
2026-06-23 20:50:03 +03:30
0909cbac7d CI: add HTTP_PROXY/HTTPS_PROXY to reach Golang toolchain (temporary solution)
Some checks failed
CI / build (push) Failing after 40s
2026-06-23 20:48:21 +03:30