feat(analytics): persona logging upgrade and Sentry system config
Add client-logging SDK, expanded event taxonomy, API observability, admin domain events UI, and move SENTRY_DSN to HQ system settings with @sentry/node bootstrap after config preload. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -14,6 +14,8 @@ import {
|
||||
import { isWechatEnv, weixinSdk } from '../lib/weixin';
|
||||
import { stripOAuthParamsFromLocation } from '@dukang/weixin-sdk';
|
||||
import WechatScanAuthModal from '../components/WechatScanAuthModal';
|
||||
import { useStorePageView } from '../lib/usePageView';
|
||||
import { trackStore } from '../lib/analytics';
|
||||
|
||||
const PENDING_SCAN_KEY = 'shop_pending_scan';
|
||||
|
||||
@@ -33,6 +35,7 @@ function formatScanError(e: unknown): string {
|
||||
}
|
||||
|
||||
export default function HomePage() {
|
||||
useStorePageView('store_home_view');
|
||||
const navigate = useNavigate();
|
||||
const { applySession } = useStoreSession();
|
||||
const [searchParams, setSearchParams] = useSearchParams();
|
||||
@@ -74,6 +77,7 @@ export default function HomePage() {
|
||||
}, [loadDashboard]);
|
||||
|
||||
async function runScan(opts?: { postAuthWarmup?: boolean }) {
|
||||
trackStore('store_redeem_scan_start');
|
||||
if (!isWechatEnv()) {
|
||||
setScanMsg('请在微信内打开门店端进行扫码核销');
|
||||
return;
|
||||
|
||||
@@ -13,8 +13,10 @@ import {
|
||||
handleShopWechatLoginResult,
|
||||
} from '../lib/wechat-auth';
|
||||
import { isWechatEnv } from '../lib/weixin';
|
||||
import { useStorePageView } from '../lib/usePageView';
|
||||
|
||||
export default function MinePage() {
|
||||
useStorePageView('store_mine_view');
|
||||
const navigate = useNavigate();
|
||||
const [searchParams, setSearchParams] = useSearchParams();
|
||||
const { resetSession, store: sessionStore, applySession } = useStoreSession();
|
||||
|
||||
@@ -4,6 +4,7 @@ import type { StorePackagesResponse } from '@dukang/shared-types';
|
||||
import PullToRefresh from '@dukang/shared-ui/PullToRefresh';
|
||||
import ShopPackagesForm from '../components/ShopPackagesForm';
|
||||
import { request } from '../lib/api';
|
||||
import { useStorePageView } from '../lib/usePageView';
|
||||
import {
|
||||
emptyPackage,
|
||||
normalizePackageFormItems,
|
||||
@@ -12,6 +13,7 @@ import {
|
||||
} from '../lib/storePackages';
|
||||
|
||||
export default function PackagesPage() {
|
||||
useStorePageView('store_packages_view');
|
||||
const navigate = useNavigate();
|
||||
const [items, setItems] = useState<PackageFormItem[]>([emptyPackage()]);
|
||||
const [pending, setPending] = useState<StorePackagesResponse['pendingRequest']>(null);
|
||||
|
||||
@@ -2,12 +2,14 @@ import { useEffect, useState } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import type { RedeemPhoneDirectPrepareResult } from '@dukang/shared-types';
|
||||
import { request } from '../lib/api';
|
||||
import { useStorePageView } from '../lib/usePageView';
|
||||
|
||||
function formatAmount(n: number) {
|
||||
return n.toLocaleString('zh-CN', { minimumFractionDigits: 2, maximumFractionDigits: 2 });
|
||||
}
|
||||
|
||||
export default function PhoneRedeemPage() {
|
||||
useStorePageView('store_phone_redeem_view');
|
||||
const navigate = useNavigate();
|
||||
const [phone, setPhone] = useState('');
|
||||
const [amount, setAmount] = useState('');
|
||||
|
||||
@@ -2,6 +2,7 @@ import { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import PullToRefresh from '@dukang/shared-ui/PullToRefresh';
|
||||
import { REDEEM_CHANNEL_LABELS, type RedeemChannel, type RedeemStatsDto } from '@dukang/shared-types';
|
||||
import { request } from '../lib/api';
|
||||
import { useStorePageView } from '../lib/usePageView';
|
||||
|
||||
type RangeKey = 'today' | '7d' | '30d';
|
||||
type StatusFilter = 'all' | 'pending' | 'paid';
|
||||
@@ -30,6 +31,7 @@ function channelLabel(channel: unknown): string {
|
||||
}
|
||||
|
||||
export default function RecordsPage() {
|
||||
useStorePageView('store_records_view');
|
||||
const [records, setRecords] = useState<Array<Record<string, unknown>>>([]);
|
||||
const [range, setRange] = useState<RangeKey>('today');
|
||||
const [statusFilter, setStatusFilter] = useState<StatusFilter>('all');
|
||||
|
||||
@@ -3,6 +3,7 @@ import { useNavigate, useSearchParams } from 'react-router-dom';
|
||||
import WeakNetFallbackPanel from '../components/WeakNetFallbackPanel';
|
||||
import { request } from '../lib/api';
|
||||
import { reportRedeemFailure } from '../lib/redeem-failure';
|
||||
import { useStorePageView } from '../lib/usePageView';
|
||||
|
||||
function formatAmount(n: number) {
|
||||
return n.toLocaleString('zh-CN', { minimumFractionDigits: 2, maximumFractionDigits: 2 });
|
||||
@@ -17,6 +18,7 @@ type Preview = {
|
||||
};
|
||||
|
||||
export default function RedeemConfirmPage() {
|
||||
useStorePageView('store_redeem_confirm_view');
|
||||
const navigate = useNavigate();
|
||||
const [searchParams] = useSearchParams();
|
||||
const [token, setToken] = useState('');
|
||||
|
||||
@@ -4,6 +4,7 @@ import { STORE_STAFF_ROLE_LABELS, type StoreStaffRole } from '@dukang/shared-typ
|
||||
import PullToRefresh from '@dukang/shared-ui/PullToRefresh';
|
||||
import { useStoreSession } from '../contexts/StoreSessionContext';
|
||||
import { getStoreProfile, request } from '../lib/api';
|
||||
import { useStorePageView } from '../lib/usePageView';
|
||||
|
||||
type StaffItem = {
|
||||
id: string;
|
||||
@@ -23,6 +24,7 @@ function maskPhone(phone: string) {
|
||||
}
|
||||
|
||||
export default function StaffPage() {
|
||||
useStorePageView('store_staff_view');
|
||||
const navigate = useNavigate();
|
||||
const { store } = useStoreSession();
|
||||
const profile = store ?? getStoreProfile();
|
||||
|
||||
@@ -8,6 +8,7 @@ import {
|
||||
} from '@dukang/shared-types';
|
||||
import PullToRefresh from '@dukang/shared-ui/PullToRefresh';
|
||||
import { request } from '../lib/api';
|
||||
import { useStorePageView } from '../lib/usePageView';
|
||||
|
||||
type StatusFilter = 'all' | StoreWithdrawStatus;
|
||||
|
||||
@@ -16,6 +17,7 @@ function formatMoney(n: number) {
|
||||
}
|
||||
|
||||
export default function WithdrawPage() {
|
||||
useStorePageView('store_withdraw_view');
|
||||
const navigate = useNavigate();
|
||||
const [summary, setSummary] = useState<StoreWithdrawSummaryDto | null>(null);
|
||||
const [items, setItems] = useState<StoreWithdrawRequestDto[]>([]);
|
||||
|
||||
Reference in New Issue
Block a user