timezone and legend display issues on summary page
This commit is contained in:
@@ -26,6 +26,7 @@ function Summary({ startDate, endDate }) {
|
||||
const params = {}
|
||||
if (startDate) params.start = startDate.toISOString()
|
||||
if (endDate) params.end = endDate.toISOString()
|
||||
params.tz_offset = -new Date().getTimezoneOffset()
|
||||
|
||||
const response = await axios.get(`${API_BASE}/analytics`, { params })
|
||||
setAnalytics(response.data)
|
||||
@@ -110,6 +111,8 @@ function Summary({ startDate, endDate }) {
|
||||
displayName: c.contact_name || formatPhoneNumber(c.address) || c.address
|
||||
}))
|
||||
|
||||
const truncate = (str, max) => str.length > max ? str.slice(0, max) + '…' : str
|
||||
|
||||
return (
|
||||
<div className="h-100 d-flex flex-column">
|
||||
<div className="bg-light border-bottom p-3">
|
||||
@@ -201,14 +204,15 @@ function Summary({ startDate, endDate }) {
|
||||
<div className="card-body">
|
||||
{topContactsData.length > 0 ? (
|
||||
<ResponsiveContainer width="100%" height={Math.max(200, topContactsData.length * 36)}>
|
||||
<BarChart data={topContactsData} layout="vertical">
|
||||
<BarChart data={topContactsData} layout="vertical" margin={{ left: 0, right: 16 }}>
|
||||
<CartesianGrid strokeDasharray="3 3" />
|
||||
<XAxis type="number" />
|
||||
<YAxis
|
||||
type="category"
|
||||
dataKey="displayName"
|
||||
width={120}
|
||||
width={160}
|
||||
tick={{ fontSize: 11 }}
|
||||
tickFormatter={(val) => truncate(val, 22)}
|
||||
/>
|
||||
<Tooltip
|
||||
formatter={(value) => [value.toLocaleString(), 'Messages']}
|
||||
|
||||
@@ -1046,7 +1046,7 @@ func SearchMessages(userDB *sql.DB, query string, limit int) ([]SearchResult, er
|
||||
}
|
||||
|
||||
// GetAnalytics retrieves analytics data for the Summary tab
|
||||
func GetAnalytics(userDB *sql.DB, startDate, endDate *time.Time, topN int) (*AnalyticsResponse, error) {
|
||||
func GetAnalytics(userDB *sql.DB, startDate, endDate *time.Time, topN int, tzOffsetMinutes int) (*AnalyticsResponse, error) {
|
||||
analytics := &AnalyticsResponse{}
|
||||
|
||||
// Build date filter
|
||||
@@ -1074,7 +1074,7 @@ func GetAnalytics(userDB *sql.DB, startDate, endDate *time.Time, topN int) (*Ana
|
||||
analytics.TopContacts = topContacts
|
||||
|
||||
// 3. Get hourly distribution
|
||||
hourly, err := getHourlyDistribution(userDB, dateFilter, args)
|
||||
hourly, err := getHourlyDistribution(userDB, dateFilter, args, tzOffsetMinutes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -1154,10 +1154,11 @@ func getTopContacts(userDB *sql.DB, dateFilter string, args []interface{}, limit
|
||||
return contacts, nil
|
||||
}
|
||||
|
||||
func getHourlyDistribution(userDB *sql.DB, dateFilter string, args []interface{}) ([]HourlyDistribution, error) {
|
||||
func getHourlyDistribution(userDB *sql.DB, dateFilter string, args []interface{}, tzOffsetMinutes int) ([]HourlyDistribution, error) {
|
||||
tzModifier := fmt.Sprintf("%+d minutes", tzOffsetMinutes)
|
||||
query := `
|
||||
SELECT
|
||||
CAST(strftime('%H', date, 'unixepoch', 'localtime') AS INTEGER) as hour,
|
||||
CAST(strftime('%H', date, 'unixepoch', '` + tzModifier + `') AS INTEGER) as hour,
|
||||
COUNT(*) as count
|
||||
FROM messages
|
||||
WHERE record_type IN (1, 2) ` + dateFilter + `
|
||||
|
||||
@@ -586,7 +586,15 @@ func HandleAnalytics(c echo.Context) error {
|
||||
}
|
||||
}
|
||||
|
||||
analytics, err := GetAnalytics(userDB, startDate, endDate, topN)
|
||||
// Timezone offset in minutes from UTC (e.g. -300 for UTC-5, 330 for UTC+5:30)
|
||||
tzOffsetMinutes := 0
|
||||
if tzStr := c.QueryParam("tz_offset"); tzStr != "" {
|
||||
if val, err := strconv.Atoi(tzStr); err == nil && val >= -840 && val <= 840 {
|
||||
tzOffsetMinutes = val
|
||||
}
|
||||
}
|
||||
|
||||
analytics, err := GetAnalytics(userDB, startDate, endDate, topN, tzOffsetMinutes)
|
||||
if err != nil {
|
||||
slog.Error("Error getting analytics", "error", err)
|
||||
return c.JSON(http.StatusInternalServerError, map[string]string{
|
||||
|
||||
Reference in New Issue
Block a user