fix: resolve 5 bugs on app overview page
- Migrate useQuery to useSWR for consistency (no mixed fetching) - Fix trend badge: guard against undefined grid and NaN comparison - Fix trend badge: hide when increase is exactly 0 - Fix version modal: use gridRef so background refetch cannot overwrite user edits - ErrorDataTable: migrate to useSWR, expose refresh() via forwardRef so the refresh button at the top also reloads the error table
This commit is contained in:
@@ -18,11 +18,15 @@ import {
|
||||
Tooltip,
|
||||
} from '@mantine/core'
|
||||
import { useDisclosure } from '@mantine/hooks'
|
||||
import { useQuery } from '@tanstack/react-query'
|
||||
import { Link } from '@tanstack/react-router'
|
||||
import dayjs from 'dayjs'
|
||||
import { useState } from 'react'
|
||||
import { forwardRef, useImperativeHandle, useState } from 'react'
|
||||
import { TbBug, TbExternalLink, TbHistory, TbMessageReport } from 'react-icons/tb'
|
||||
import useSWR from 'swr'
|
||||
|
||||
export interface ErrorDataTableHandle {
|
||||
refresh: () => void
|
||||
}
|
||||
|
||||
export interface ErrorDataTableProps {
|
||||
appId?: string
|
||||
@@ -45,15 +49,20 @@ const STATUS_LABEL: Record<string, string> = {
|
||||
CLOSED: 'Closed',
|
||||
}
|
||||
|
||||
export function ErrorDataTable({ appId }: ErrorDataTableProps) {
|
||||
const fetcher = (url: string) => fetch(url).then((r) => r.json())
|
||||
|
||||
export const ErrorDataTable = forwardRef<ErrorDataTableHandle, ErrorDataTableProps>(
|
||||
function ErrorDataTable({ appId }, ref) {
|
||||
const [opened, { open, close }] = useDisclosure(false)
|
||||
const [selectedError, setSelectedError] = useState<any>(null)
|
||||
const [showStackTrace, setShowStackTrace] = useState(false)
|
||||
|
||||
const { data: bugsData, isLoading } = useQuery({
|
||||
queryKey: ['bugs', appId],
|
||||
queryFn: () => fetch(`/api/bugs?app=${appId || 'all'}&limit=10`).then((r) => r.json()),
|
||||
})
|
||||
const { data: bugsData, isLoading, mutate } = useSWR(
|
||||
`/api/bugs?app=${appId || 'all'}&limit=10`,
|
||||
fetcher
|
||||
)
|
||||
|
||||
useImperativeHandle(ref, () => ({ refresh: mutate }))
|
||||
|
||||
const bugs = bugsData?.data || []
|
||||
|
||||
@@ -257,4 +266,4 @@ export function ErrorDataTable({ appId }: ErrorDataTableProps) {
|
||||
</Drawer>
|
||||
</>
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { useQuery } from '@tanstack/react-query'
|
||||
import { VillageActivityLineChart, VillageComparisonBarChart } from '@/frontend/components/DashboardCharts'
|
||||
import { ErrorDataTable } from '@/frontend/components/ErrorDataTable'
|
||||
import { ErrorDataTable, type ErrorDataTableHandle } from '@/frontend/components/ErrorDataTable'
|
||||
import { SummaryCard } from '@/frontend/components/SummaryCard'
|
||||
import { useSession } from '@/frontend/hooks/useAuth'
|
||||
import {
|
||||
@@ -21,7 +20,7 @@ import {
|
||||
import { useDisclosure } from '@mantine/hooks'
|
||||
import { notifications } from '@mantine/notifications'
|
||||
import { createFileRoute, useNavigate, useParams } from '@tanstack/react-router'
|
||||
import { useEffect, useState } from 'react'
|
||||
import { useEffect, useRef, useState } from 'react'
|
||||
import {
|
||||
TbActivity,
|
||||
TbAlertTriangle,
|
||||
@@ -45,6 +44,7 @@ function AppOverviewPage() {
|
||||
const [versionModalOpened, { open: openVersionModal, close: closeVersionModal }] = useDisclosure(false)
|
||||
const { data: session } = useSession()
|
||||
const isDeveloper = session?.user?.role === 'DEVELOPER'
|
||||
const errorTableRef = useRef<ErrorDataTableHandle>(null)
|
||||
|
||||
const [latestVersion, setLatestVersion] = useState('')
|
||||
const [minVersion, setMinVersion] = useState('')
|
||||
@@ -56,28 +56,31 @@ function AppOverviewPage() {
|
||||
const { data: dailyRes, isLoading: dailyLoading, mutate: mutateDaily } = useSWR(isDesaPlus ? API_URLS.getDailyActivity() : null, fetcher)
|
||||
const { data: comparisonRes, isLoading: comparisonLoading, mutate: mutateComparison } = useSWR(isDesaPlus ? API_URLS.getComparisonActivity() : null, fetcher)
|
||||
|
||||
const { data: appData, isLoading: appLoading } = useQuery({
|
||||
queryKey: ['apps', appId],
|
||||
queryFn: () => fetch(`/api/apps/${appId}`).then((r) => r.json()),
|
||||
})
|
||||
const { data: appData, isLoading: appLoading } = useSWR(`/api/apps/${appId}`, fetcher)
|
||||
|
||||
const grid = gridRes?.data
|
||||
const dailyData = dailyRes?.data || []
|
||||
const comparisonData = comparisonRes?.data || []
|
||||
|
||||
// Ref so the modal-sync effect always reads current grid without re-running on every background refetch
|
||||
const gridRef = useRef(grid)
|
||||
gridRef.current = grid
|
||||
|
||||
useEffect(() => {
|
||||
if (grid?.version && versionModalOpened) {
|
||||
setLatestVersion(grid.version.mobile_latest_version || '')
|
||||
setMinVersion(grid.version.mobile_minimum_version || '')
|
||||
setMessageUpdate(grid.version.mobile_message_update || '')
|
||||
setMaintenance(grid.version.mobile_maintenance === 'true')
|
||||
if (versionModalOpened && gridRef.current?.version) {
|
||||
const v = gridRef.current.version
|
||||
setLatestVersion(v.mobile_latest_version || '')
|
||||
setMinVersion(v.mobile_minimum_version || '')
|
||||
setMessageUpdate(v.mobile_message_update || '')
|
||||
setMaintenance(v.mobile_maintenance === 'true')
|
||||
}
|
||||
}, [grid, versionModalOpened])
|
||||
}, [versionModalOpened])
|
||||
|
||||
const handleRefresh = () => {
|
||||
mutateGrid()
|
||||
mutateDaily()
|
||||
mutateComparison()
|
||||
errorTableRef.current?.refresh()
|
||||
}
|
||||
|
||||
const handleSaveVersion = async () => {
|
||||
@@ -214,8 +217,8 @@ function AppOverviewPage() {
|
||||
value={gridLoading ? '...' : (grid?.activity?.today?.toLocaleString() ?? '0')}
|
||||
icon={TbActivity}
|
||||
color="teal"
|
||||
trend={grid?.activity?.increase
|
||||
? { value: `${grid.activity.increase}%`, positive: grid.activity.increase > 0 }
|
||||
trend={grid?.activity?.increase != null && Number(grid.activity.increase) !== 0
|
||||
? { value: `${grid.activity.increase}%`, positive: Number(grid.activity.increase) > 0 }
|
||||
: undefined}
|
||||
/>
|
||||
|
||||
@@ -254,7 +257,7 @@ function AppOverviewPage() {
|
||||
<VillageComparisonBarChart data={comparisonData} isLoading={comparisonLoading} />
|
||||
</SimpleGrid>
|
||||
|
||||
<ErrorDataTable appId={appId} />
|
||||
<ErrorDataTable ref={errorTableRef} appId={appId} />
|
||||
</Stack>
|
||||
</>
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user