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
This commit is contained in:
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -125,6 +126,21 @@ func (h *Handler) handleHistoryCallback(ctx context.Context, chatID int64, msgID
|
||||
h.editEventTimeMin(ctx, chatID, msgID, user, eid, hh, loc)
|
||||
return
|
||||
}
|
||||
// Add IN event — show hour picker
|
||||
if strings.HasPrefix(data, "addin_") {
|
||||
h.addEventTime(ctx, chatID, msgID, user, data[6:], "in", loc)
|
||||
return
|
||||
}
|
||||
// Add OUT event — show hour picker
|
||||
if strings.HasPrefix(data, "addout_") {
|
||||
h.addEventTime(ctx, chatID, msgID, user, data[7:], "out", loc)
|
||||
return
|
||||
}
|
||||
// Add event hour/minute callbacks
|
||||
if strings.HasPrefix(data, "addtm_") {
|
||||
h.handleAddEventTime(ctx, chatID, msgID, user, data[6:], loc)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// sendCalendar sends a calendar view as a new message.
|
||||
@@ -245,6 +261,8 @@ func (h *Handler) sendDayView(ctx context.Context, chatID int64, msgID int, user
|
||||
text += "\nNo events for this day."
|
||||
kb := models.InlineKeyboardMarkup{
|
||||
InlineKeyboard: [][]models.InlineKeyboardButton{
|
||||
{{Text: "Add IN", CallbackData: "addin_" + date}},
|
||||
{{Text: "Add OUT", CallbackData: "addout_" + date}},
|
||||
{{Text: "Back to Calendar", CallbackData: "history"}},
|
||||
},
|
||||
}
|
||||
@@ -279,6 +297,11 @@ func (h *Handler) sendDayView(ctx context.Context, chatID int64, msgID int, user
|
||||
})
|
||||
}
|
||||
|
||||
kbRows = append(kbRows, []models.InlineKeyboardButton{
|
||||
{Text: "Add IN", CallbackData: "addin_" + date},
|
||||
{Text: "Add OUT", CallbackData: "addout_" + date},
|
||||
})
|
||||
|
||||
kbRows = append(kbRows, []models.InlineKeyboardButton{
|
||||
{Text: "Back to Calendar", CallbackData: "history"},
|
||||
})
|
||||
@@ -490,3 +513,99 @@ func (h *Handler) getEventByID(userID, eventID int64) (*db.Event, error) {
|
||||
}
|
||||
return &e, nil
|
||||
}
|
||||
|
||||
// addEventTime shows an hour picker for adding a new event to a day.
|
||||
func (h *Handler) addEventTime(ctx context.Context, chatID int64, msgID int, user *db.User, date, eventType string, loc *time.Location) {
|
||||
text := fmt.Sprintf("Select hour for %s event:", eventType)
|
||||
kbRows := [][]models.InlineKeyboardButton{}
|
||||
hourRow := []models.InlineKeyboardButton{}
|
||||
for hh := 0; hh < 24; hh++ {
|
||||
hourRow = append(hourRow, models.InlineKeyboardButton{
|
||||
Text: fmt.Sprintf("%02d", hh),
|
||||
CallbackData: fmt.Sprintf("addtm_%s_%s_%02d", eventType, date, hh),
|
||||
})
|
||||
if len(hourRow) == 6 || hh == 23 {
|
||||
kbRows = append(kbRows, hourRow)
|
||||
hourRow = nil
|
||||
}
|
||||
}
|
||||
kbRows = append(kbRows, []models.InlineKeyboardButton{
|
||||
{Text: "Back", CallbackData: "cal_day_" + date},
|
||||
})
|
||||
kb := models.InlineKeyboardMarkup{InlineKeyboard: kbRows}
|
||||
h.Bot.EditMessageText(ctx, &bot.EditMessageTextParams{
|
||||
ChatID: chatID, MessageID: msgID, Text: text, ReplyMarkup: &kb,
|
||||
})
|
||||
}
|
||||
|
||||
// addEventTimeMin shows a minute picker (15-min intervals) after hour selection for adding an event.
|
||||
func (h *Handler) addEventTimeMin(ctx context.Context, chatID int64, msgID int, user *db.User, date, eventType string, hh int, loc *time.Location) {
|
||||
text := fmt.Sprintf("Select minute for hour %02d:", hh)
|
||||
kbRows := [][]models.InlineKeyboardButton{}
|
||||
minRow := []models.InlineKeyboardButton{}
|
||||
for _, mm := range []int{0, 15, 30, 45} {
|
||||
minRow = append(minRow, models.InlineKeyboardButton{
|
||||
Text: fmt.Sprintf("%02d", mm),
|
||||
CallbackData: fmt.Sprintf("addtm_%s_%s_%02d_%02d", eventType, date, hh, mm),
|
||||
})
|
||||
}
|
||||
kbRows = append(kbRows, minRow)
|
||||
kbRows = append(kbRows, []models.InlineKeyboardButton{
|
||||
{Text: "Back", CallbackData: "add" + eventType + "_" + date},
|
||||
})
|
||||
kb := models.InlineKeyboardMarkup{InlineKeyboard: kbRows}
|
||||
h.Bot.EditMessageText(ctx, &bot.EditMessageTextParams{
|
||||
ChatID: chatID, MessageID: msgID, Text: text, ReplyMarkup: &kb,
|
||||
})
|
||||
}
|
||||
|
||||
// addEventDo creates a new event at the specified time and returns to the day view.
|
||||
func (h *Handler) addEventDo(ctx context.Context, chatID int64, msgID int, user *db.User, date, eventType string, hh, mm int, loc *time.Location) {
|
||||
t, err := time.ParseInLocation("2006-01-02 15:04", date+" "+fmt.Sprintf("%02d:%02d", hh, mm), loc)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
day, err := h.DB.GetOrCreateDay(user.ID, date)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
var wt *int64
|
||||
if eventType == "in" {
|
||||
wt = &day.CurrentWorkTypeID
|
||||
if *wt == 0 {
|
||||
wt = nil
|
||||
}
|
||||
}
|
||||
|
||||
if err := h.DB.CreateEvent(user.ID, day.ID, eventType, wt, t.Unix(), ""); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
h.sendDayView(ctx, chatID, msgID, user, date, loc, false)
|
||||
}
|
||||
|
||||
// handleAddEventTime parses the addtm_ callback and dispatches to the minute picker or event creation.
|
||||
func (h *Handler) handleAddEventTime(ctx context.Context, chatID int64, msgID int, user *db.User, payload string, loc *time.Location) {
|
||||
parts := strings.SplitN(payload, "_", 4)
|
||||
if len(parts) < 3 {
|
||||
return
|
||||
}
|
||||
eventType := parts[0]
|
||||
addDate := parts[1]
|
||||
hh, err := strconv.Atoi(parts[2])
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if len(parts) == 3 {
|
||||
h.addEventTimeMin(ctx, chatID, msgID, user, addDate, eventType, hh, loc)
|
||||
return
|
||||
}
|
||||
mm, err := strconv.Atoi(parts[3])
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
h.addEventDo(ctx, chatID, msgID, user, addDate, eventType, hh, mm, loc)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user