Файли
2026-11-07 20:55:19 +00:00

123 рядки
3.4 KiB
Go

package item
import (
"fmt"
"strconv"
"strings"
"git.entityseven.com/rilaxik/pllist/internal/domain"
"git.entityseven.com/rilaxik/pllist/internal/service"
"git.entityseven.com/rilaxik/pllist/internal/telegram/shared"
)
const (
addItemPrompt = "Send the item title (1-200 characters). /cancel to stop."
renameItemPrompt = "Send the new item title (1-200 characters). /cancel to stop."
notePrompt = "Send the item note (up to 1000 characters). /cancel to stop."
quantityPrompt = "Send the quantity (positive number, e.g. 1.5). /cancel to stop."
deleteItemText = "Delete this item? This cannot be undone."
itemTruncateLength = 60
)
func listMenuText(itemPage service.ItemPage) string {
var text strings.Builder
fmt.Fprintf(&text, "<b>%s</b>\nRole: %s\n\n",
shared.Escape(itemPage.Access.List.Title), itemPage.Access.Role)
writeItemsText(&text, itemPage)
if itemPage.Total > len(itemPage.Items) {
fmt.Fprintf(&text, "\n\nShowing %d of %d. Open Manage items for the rest.",
len(itemPage.Items), itemPage.Total)
}
return text.String()
}
func itemsText(itemPage service.ItemPage) string {
var text strings.Builder
fmt.Fprintf(&text, "<b>%s</b>\n\n", shared.Escape(itemPage.Access.List.Title))
writeItemsText(&text, itemPage)
if itemPage.Total > 0 {
fmt.Fprintf(&text, "\n\nPage %d/%d\nTap an item to manage it.",
itemPage.Page, itemPage.PageCount())
}
return text.String()
}
func writeItemsText(text *strings.Builder, itemPage service.ItemPage) {
text.WriteString("<b>Items:</b>\n")
if itemPage.Total == 0 {
text.WriteString("No items yet.\n\n<i>0 items</i>")
return
}
for _, item := range itemPage.Items {
fmt.Fprintf(text, "%s %s\n", itemIcon(item), shared.Escape(titleWithQuantity(item)))
}
fmt.Fprintf(text, "\n<i>%s</i>", itemCountLabel(itemPage.Total))
}
func itemCountLabel(total int) string {
label := "items"
if total == 1 {
label = "item"
}
return fmt.Sprintf("%d %s", total, label)
}
func itemText(itemAccess service.ItemAccess, userID int64) string {
item := itemAccess.Item
var text strings.Builder
fmt.Fprintf(&text, "<b>%s %s</b>\nStatus: %s\n",
itemIcon(item), shared.Escape(titleWithQuantity(item)), item.Status)
if item.Note != "" {
fmt.Fprintf(&text, "Note: %s\n", shared.Escape(item.Note))
}
switch {
case !item.Reserved():
text.WriteString("Reserved: no")
case item.ReservedByID != nil && *item.ReservedByID == userID:
text.WriteString("Reserved: yes (you)")
default:
text.WriteString("Reserved: yes")
}
return text.String()
}
func itemLabel(item domain.Item, userID int64) string {
title := shared.Truncate(item.Title, 32)
label := fmt.Sprintf("%s %s x%s", itemIcon(item), title, formatQuantity(item.Quantity))
if item.Reserved() {
if item.ReservedByID != nil && *item.ReservedByID == userID {
label += " · yours"
} else {
label += " · reserved"
}
}
return shared.Truncate(label, itemTruncateLength)
}
func itemIcon(item domain.Item) string {
if item.Done() {
return "✓"
}
return urgencyEmoji(item.Urgency)
}
func titleWithQuantity(item domain.Item) string {
return fmt.Sprintf("%s x%s", item.Title, formatQuantity(item.Quantity))
}
func formatQuantity(quantity float64) string {
return strconv.FormatFloat(quantity, 'f', -1, 64)
}
func urgencyEmoji(urgency domain.Urgency) string {
switch urgency {
case domain.UrgencyHigh:
return "🔴"
case domain.UrgencyLow:
return "🟢"
default:
return "🟡"
}
}