feat(payment): enhance payment method configuration with icons and improve UI interactions
This commit is contained in:
+107
-31
@@ -16,7 +16,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
For commercial licensing, please contact support@quantumnous.com
|
||||
*/
|
||||
import { useState, useEffect, useCallback, useMemo } from 'react'
|
||||
import { useState, useCallback, useMemo } from 'react'
|
||||
import { useQueryClient, useIsFetching } from '@tanstack/react-query'
|
||||
import { useNavigate, getRouteApi } from '@tanstack/react-router'
|
||||
import { type Table } from '@tanstack/react-table'
|
||||
@@ -51,12 +51,57 @@ import {
|
||||
import { useUsageLogsContext } from './usage-logs-provider'
|
||||
|
||||
const route = getRouteApi('/_authenticated/usage-logs/$section')
|
||||
const logTypeValues = ['0', '1', '2', '3', '4', '5', '6'] as const
|
||||
|
||||
type LogTypeValue = (typeof logTypeValues)[number]
|
||||
type LogTypeValue = (typeof LOG_TYPE_FILTERS)[number]['value']
|
||||
const logTypeValueSet = new Set<string>(
|
||||
LOG_TYPE_FILTERS.map((type) => type.value)
|
||||
)
|
||||
|
||||
type CommonLogDraft = {
|
||||
sourceKey: string
|
||||
filters: CommonLogFilters
|
||||
logType: LogTypeValue
|
||||
}
|
||||
|
||||
function isLogTypeValue(value: string): value is LogTypeValue {
|
||||
return (logTypeValues as readonly string[]).includes(value)
|
||||
return logTypeValueSet.has(value)
|
||||
}
|
||||
|
||||
function getLogTypeValue(value: unknown): LogTypeValue {
|
||||
return Array.isArray(value) &&
|
||||
value.length === 1 &&
|
||||
typeof value[0] === 'string' &&
|
||||
isLogTypeValue(value[0])
|
||||
? value[0]
|
||||
: LOG_TYPE_ALL_VALUE
|
||||
}
|
||||
|
||||
function buildSearchSourceKey(values: {
|
||||
startTime?: unknown
|
||||
endTime?: unknown
|
||||
channel?: unknown
|
||||
model?: unknown
|
||||
token?: unknown
|
||||
group?: unknown
|
||||
username?: unknown
|
||||
requestId?: unknown
|
||||
upstreamRequestId?: unknown
|
||||
type?: unknown
|
||||
}) {
|
||||
return [
|
||||
values.startTime,
|
||||
values.endTime,
|
||||
values.channel,
|
||||
values.model,
|
||||
values.token,
|
||||
values.group,
|
||||
values.username,
|
||||
values.requestId,
|
||||
values.upstreamRequestId,
|
||||
Array.isArray(values.type) ? values.type.join(',') : values.type,
|
||||
]
|
||||
.map((value) => String(value ?? ''))
|
||||
.join('\u001f')
|
||||
}
|
||||
|
||||
interface CommonLogsFilterBarProps<TData> {
|
||||
@@ -74,15 +119,21 @@ export function CommonLogsFilterBar<TData>(
|
||||
const { sensitiveVisible, setSensitiveVisible } = useUsageLogsContext()
|
||||
const fetchingLogs = useIsFetching({ queryKey: ['logs'] })
|
||||
|
||||
const [filters, setFilters] = useState<CommonLogFilters>(() => {
|
||||
const searchState = useMemo<CommonLogDraft>(() => {
|
||||
const { start, end } = getDefaultTimeRange()
|
||||
return { startTime: start, endTime: end }
|
||||
})
|
||||
const [logType, setLogType] = useState<LogTypeValue>(LOG_TYPE_ALL_VALUE)
|
||||
|
||||
useEffect(() => {
|
||||
const { start, end } = getDefaultTimeRange()
|
||||
setFilters({
|
||||
const sourceValues = {
|
||||
startTime: searchParams.startTime,
|
||||
endTime: searchParams.endTime,
|
||||
channel: searchParams.channel,
|
||||
model: searchParams.model,
|
||||
token: searchParams.token,
|
||||
group: searchParams.group,
|
||||
username: searchParams.username,
|
||||
requestId: searchParams.requestId,
|
||||
upstreamRequestId: searchParams.upstreamRequestId,
|
||||
type: searchParams.type,
|
||||
}
|
||||
const filters: CommonLogFilters = {
|
||||
startTime: searchParams.startTime
|
||||
? new Date(searchParams.startTime)
|
||||
: start,
|
||||
@@ -94,16 +145,12 @@ export function CommonLogsFilterBar<TData>(
|
||||
username: searchParams.username || undefined,
|
||||
requestId: searchParams.requestId || undefined,
|
||||
upstreamRequestId: searchParams.upstreamRequestId || undefined,
|
||||
})
|
||||
|
||||
const typeArr = searchParams.type
|
||||
const nextLogType =
|
||||
Array.isArray(typeArr) &&
|
||||
typeArr.length === 1 &&
|
||||
isLogTypeValue(typeArr[0])
|
||||
? typeArr[0]
|
||||
: LOG_TYPE_ALL_VALUE
|
||||
setLogType(nextLogType)
|
||||
}
|
||||
return {
|
||||
sourceKey: buildSearchSourceKey(sourceValues),
|
||||
filters,
|
||||
logType: getLogTypeValue(searchParams.type),
|
||||
}
|
||||
}, [
|
||||
searchParams.startTime,
|
||||
searchParams.endTime,
|
||||
@@ -116,12 +163,25 @@ export function CommonLogsFilterBar<TData>(
|
||||
searchParams.upstreamRequestId,
|
||||
searchParams.type,
|
||||
])
|
||||
const [draft, setDraft] = useState<CommonLogDraft>(() => searchState)
|
||||
const activeDraft =
|
||||
draft.sourceKey === searchState.sourceKey ? draft : searchState
|
||||
const filters = activeDraft.filters
|
||||
const logType = activeDraft.logType
|
||||
|
||||
const handleChange = useCallback(
|
||||
(field: keyof CommonLogFilters, value: Date | string | undefined) => {
|
||||
setFilters((prev) => ({ ...prev, [field]: value }))
|
||||
setDraft((current) => {
|
||||
const base =
|
||||
current.sourceKey === searchState.sourceKey ? current : searchState
|
||||
return {
|
||||
sourceKey: searchState.sourceKey,
|
||||
filters: { ...base.filters, [field]: value },
|
||||
logType: base.logType,
|
||||
}
|
||||
})
|
||||
},
|
||||
[]
|
||||
[searchState]
|
||||
)
|
||||
|
||||
const handleApply = useCallback(() => {
|
||||
@@ -142,17 +202,23 @@ export function CommonLogsFilterBar<TData>(
|
||||
const handleReset = useCallback(() => {
|
||||
const { start, end } = getDefaultTimeRange()
|
||||
const resetFilters: CommonLogFilters = { startTime: start, endTime: end }
|
||||
setFilters(resetFilters)
|
||||
setLogType(LOG_TYPE_ALL_VALUE)
|
||||
const resetSearch = {
|
||||
type: [LOG_TYPE_ALL_VALUE],
|
||||
startTime: start.getTime(),
|
||||
endTime: end.getTime(),
|
||||
}
|
||||
setDraft({
|
||||
sourceKey: buildSearchSourceKey(resetSearch),
|
||||
filters: resetFilters,
|
||||
logType: LOG_TYPE_ALL_VALUE,
|
||||
})
|
||||
|
||||
navigate({
|
||||
to: '/usage-logs/$section',
|
||||
params: { section: 'common' },
|
||||
search: {
|
||||
page: 1,
|
||||
type: [LOG_TYPE_ALL_VALUE],
|
||||
startTime: start.getTime(),
|
||||
endTime: end.getTime(),
|
||||
...resetSearch,
|
||||
},
|
||||
})
|
||||
queryClient.invalidateQueries({ queryKey: ['logs'] })
|
||||
@@ -259,9 +325,19 @@ export function CommonLogsFilterBar<TData>(
|
||||
items={logTypeItems}
|
||||
value={logType}
|
||||
onValueChange={(value) => {
|
||||
setLogType(
|
||||
const nextLogType =
|
||||
value !== null && isLogTypeValue(value) ? value : LOG_TYPE_ALL_VALUE
|
||||
)
|
||||
setDraft((current) => {
|
||||
const base =
|
||||
current.sourceKey === searchState.sourceKey
|
||||
? current
|
||||
: searchState
|
||||
return {
|
||||
sourceKey: searchState.sourceKey,
|
||||
filters: base.filters,
|
||||
logType: nextLogType,
|
||||
}
|
||||
})
|
||||
}}
|
||||
>
|
||||
<SelectTrigger>
|
||||
|
||||
Reference in New Issue
Block a user