添加卡牌设置功能,更新状态管理和界面显示逻辑

This commit is contained in:
yuchenglong
2026-01-20 10:12:12 +08:00
parent 97f61e68bd
commit 08d05df8be
7 changed files with 242 additions and 38 deletions

View File

@@ -37,7 +37,7 @@ const BOOKMAKERS = [
export default function ProfileScreen() { export default function ProfileScreen() {
const { theme, toggleTheme, setTheme, isSystemTheme, useSystemTheme } = const { theme, toggleTheme, setTheme, isSystemTheme, useSystemTheme } =
useTheme(); useTheme();
const { state, updateOddsSettings } = useAppState(); const { state, updateOddsSettings, updateCardsSettings } = useAppState();
const { t, i18n } = useTranslation(); const { t, i18n } = useTranslation();
const router = useRouter(); const router = useRouter();
const isDark = theme === "dark"; const isDark = theme === "dark";
@@ -55,6 +55,13 @@ export default function ProfileScreen() {
}); });
}; };
const toggleCards = () => {
updateCardsSettings({
...state.cardsSettings,
enabled: !state.cardsSettings.enabled,
});
};
const selectBookmaker = (name: string) => { const selectBookmaker = (name: string) => {
const current = state.oddsSettings.selectedBookmakers; const current = state.oddsSettings.selectedBookmakers;
let next: string[]; let next: string[];
@@ -429,6 +436,38 @@ export default function ProfileScreen() {
</View> </View>
</View> </View>
<ThemedText style={styles.sectionTitle}>
{t("settings.cards_title")}
</ThemedText>
<View
style={[
styles.section,
{ backgroundColor: isDark ? "#1c1c1e" : "#fff" },
]}
>
<View style={styles.settingItem}>
<View style={styles.settingLabel}>
<IconSymbol
name="id-card"
size={20}
color={iconColor}
style={{ marginRight: 10 }}
/>
<ThemedText>{t("settings.cards_show")}</ThemedText>
</View>
<View style={styles.settingControl}>
<TouchableOpacity onPress={toggleCards} style={styles.button}>
<ThemedText>
{state.cardsSettings.enabled
? t("settings.cards_enabled")
: t("settings.cards_disabled")}
</ThemedText>
</TouchableOpacity>
</View>
</View>
</View>
{/* <ThemedText style={styles.sectionTitle}>登录</ThemedText> {/* <ThemedText style={styles.sectionTitle}>登录</ThemedText>
<View <View

View File

@@ -3,8 +3,13 @@ import { IconSymbol } from "@/components/ui/icon-symbol";
import { Colors } from "@/constants/theme"; import { Colors } from "@/constants/theme";
import { useAppState } from "@/context/AppStateContext"; import { useAppState } from "@/context/AppStateContext";
import { useTheme } from "@/context/ThemeContext"; import { useTheme } from "@/context/ThemeContext";
import { addFavorite, fetchOdds, removeFavorite } from "@/lib/api"; import {
import { Match, OddsItem } from "@/types/api"; addFavorite,
fetchLiveScore,
fetchOdds,
removeFavorite,
} from "@/lib/api";
import { LiveScoreMatch, Match, OddsItem } from "@/types/api";
import { Image } from "expo-image"; import { Image } from "expo-image";
import { LinearGradient } from "expo-linear-gradient"; import { LinearGradient } from "expo-linear-gradient";
import { useRouter } from "expo-router"; import { useRouter } from "expo-router";
@@ -28,9 +33,11 @@ export function MatchCard({
const [isFav, setIsFav] = useState(match.fav); const [isFav, setIsFav] = useState(match.fav);
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const [odds, setOdds] = useState<OddsItem[]>(match.odds || []); const [odds, setOdds] = useState<OddsItem[]>(match.odds || []);
const [liveDetail, setLiveDetail] = useState<LiveScoreMatch | null>(null);
// console.log("MatchCard render:", JSON.stringify(match)); // console.log("MatchCard render:", JSON.stringify(match));
const oddsSettings = state.oddsSettings; const oddsSettings = state.oddsSettings;
const cardsSettings = state.cardsSettings;
useEffect(() => { useEffect(() => {
if ( if (
@@ -52,6 +59,20 @@ export function MatchCard({
match.odds, match.odds,
]); ]);
// Fetch live score detail for cards info
useEffect(() => {
if (cardsSettings.enabled && isLive && match.leagueKey) {
fetchLiveScore(match.sportId || 1, Number(match.leagueKey))
.then((matches) => {
const detail = matches.find((m) => String(m.event_key) === match.id);
if (detail) {
setLiveDetail(detail);
}
})
.catch((err) => console.log("Fetch live detail for cards error:", err));
}
}, [cardsSettings.enabled, match.id, match.leagueKey, match.sportId]);
// 当外部传入的 match.fav 改变时,更新内部状态 // 当外部传入的 match.fav 改变时,更新内部状态
useEffect(() => { useEffect(() => {
setIsFav(match.fav); setIsFav(match.fav);
@@ -90,10 +111,53 @@ export function MatchCard({
if (m) return { home: m[1], away: m[2], hasScore: true }; if (m) return { home: m[1], away: m[2], hasScore: true };
if (s && s !== "-" && s !== "0 - 0") if (s && s !== "-" && s !== "0 - 0")
return { home: s, away: "", hasScore: true }; return { home: s, away: "", hasScore: true };
if (s === "0 - 0") return { home: "0", away: "0", hasScore: true }; if (s === "0 - 0" || s === "0-0")
return { home: "0", away: "0", hasScore: true };
return { home: "", away: "", hasScore: false }; return { home: "", away: "", hasScore: false };
}, [match.scoreText]); }, [match.scoreText]);
const cardsCount = React.useMemo(() => {
if (!liveDetail?.cards || !cardsSettings.enabled) {
return { homeYellow: 0, homeRed: 0, awayYellow: 0, awayRed: 0 };
}
let homeYellow = 0,
homeRed = 0,
awayYellow = 0,
awayRed = 0;
liveDetail.cards.forEach((card) => {
const cardType = (card.card || "").toLowerCase();
const isYellow = cardType.includes("yellow");
const isRed = cardType.includes("red");
if (!isYellow && !isRed) return;
const info = (card.info || "").toLowerCase();
const sideFromInfo = info.includes("home")
? "home"
: info.includes("away")
? "away"
: null;
const sideFromFault = card.home_fault
? "home"
: card.away_fault
? "away"
: null;
const side = sideFromInfo || sideFromFault;
if (!side) return;
if (side === "home") {
if (isYellow) homeYellow++;
if (isRed) homeRed++;
} else {
if (isYellow) awayYellow++;
if (isRed) awayRed++;
}
});
return { homeYellow, homeRed, awayYellow, awayRed };
}, [liveDetail, cardsSettings.enabled]);
const handlePress = () => { const handlePress = () => {
if (onPress) { if (onPress) {
onPress(match); onPress(match);
@@ -191,6 +255,30 @@ export function MatchCard({
); );
}; };
const renderCardsInline = (yellow: number, red: number) => {
if (!cardsSettings.enabled || !liveDetail) return null;
if (yellow <= 0 && red <= 0) return null;
return (
<View style={styles.cardsInline}>
{yellow > 0 && (
<View style={[styles.cardBadge, styles.cardBadgeYellow]}>
<ThemedText
style={[styles.cardBadgeText, styles.cardBadgeTextDark]}
>
{yellow}
</ThemedText>
</View>
)}
{red > 0 && (
<View style={[styles.cardBadge, styles.cardBadgeRed]}>
<ThemedText style={styles.cardBadgeText}>{red}</ThemedText>
</View>
)}
</View>
);
};
return ( return (
<Pressable <Pressable
onPress={handlePress} onPress={handlePress}
@@ -244,6 +332,7 @@ export function MatchCard({
> >
{match.homeTeamName || match.home} {match.homeTeamName || match.home}
</ThemedText> </ThemedText>
{renderCardsInline(cardsCount.homeYellow, cardsCount.homeRed)}
</View> </View>
{renderOddsRow(oddsSettings.selectedBookmakers[0], true)} {renderOddsRow(oddsSettings.selectedBookmakers[0], true)}
</View> </View>
@@ -265,6 +354,7 @@ export function MatchCard({
> >
{match.awayTeamName || match.away} {match.awayTeamName || match.away}
</ThemedText> </ThemedText>
{renderCardsInline(cardsCount.awayYellow, cardsCount.awayRed)}
</View> </View>
{renderOddsRow(oddsSettings.selectedBookmakers[1], false)} {renderOddsRow(oddsSettings.selectedBookmakers[1], false)}
</View> </View>
@@ -368,7 +458,7 @@ const styles = StyleSheet.create({
flexDirection: "row", flexDirection: "row",
alignItems: "center", alignItems: "center",
flex: 1, flex: 1,
marginRight: 6, minWidth: 0,
}, },
teamLogo: { teamLogo: {
width: 22, width: 22,
@@ -379,6 +469,7 @@ const styles = StyleSheet.create({
fontWeight: "600", fontWeight: "600",
marginLeft: 6, marginLeft: 6,
flex: 1, flex: 1,
minWidth: 0,
}, },
bookmakerOddsRow: { bookmakerOddsRow: {
flexDirection: "row", flexDirection: "row",
@@ -427,4 +518,34 @@ const styles = StyleSheet.create({
width: 36, width: 36,
height: 54, height: 54,
}, },
cardsInline: {
flexDirection: "row",
alignItems: "center",
gap: 4,
marginLeft: 6,
flexShrink: 0,
},
cardBadge: {
minWidth: 16,
height: 16,
borderRadius: 3,
alignItems: "center",
justifyContent: "center",
paddingHorizontal: 3,
},
cardBadgeYellow: {
backgroundColor: "#FFC400",
},
cardBadgeRed: {
backgroundColor: "#FF3B30",
},
cardBadgeText: {
fontSize: 10,
fontWeight: "900",
lineHeight: 12,
color: "#fff",
},
cardBadgeTextDark: {
color: "#000",
},
}); });

View File

@@ -1,4 +1,4 @@
import { OddsSettings, storage } from "@/lib/storage"; import { CardsSettings, OddsSettings, storage } from "@/lib/storage";
import React, { import React, {
createContext, createContext,
ReactNode, ReactNode,
@@ -13,6 +13,7 @@ interface AppState {
selectedLeagueKey: string | null; selectedLeagueKey: string | null;
timezone: string; timezone: string;
oddsSettings: OddsSettings; oddsSettings: OddsSettings;
cardsSettings: CardsSettings;
} }
interface AppStateContextType { interface AppStateContextType {
@@ -22,6 +23,7 @@ interface AppStateContextType {
updateLeagueKey: (leagueKey: string | null) => void; updateLeagueKey: (leagueKey: string | null) => void;
updateTimezone: (timezone: string) => void; updateTimezone: (timezone: string) => void;
updateOddsSettings: (settings: OddsSettings) => void; updateOddsSettings: (settings: OddsSettings) => void;
updateCardsSettings: (settings: CardsSettings) => void;
} }
const AppStateContext = createContext<AppStateContextType | undefined>( const AppStateContext = createContext<AppStateContextType | undefined>(
@@ -35,13 +37,17 @@ export function AppStateProvider({ children }: { children: ReactNode }) {
selectedLeagueKey: null, selectedLeagueKey: null,
timezone: "UTC", timezone: "UTC",
oddsSettings: { enabled: false, selectedBookmakers: [] }, oddsSettings: { enabled: false, selectedBookmakers: [] },
cardsSettings: { enabled: false },
}); });
useEffect(() => { useEffect(() => {
// Initial load of odds settings // Initial load of odds settings and cards settings
storage.getOddsSettings().then((settings) => { storage.getOddsSettings().then((settings) => {
setState((prev) => ({ ...prev, oddsSettings: settings })); setState((prev) => ({ ...prev, oddsSettings: settings }));
}); });
storage.getCardsSettings().then((settings) => {
setState((prev) => ({ ...prev, cardsSettings: settings }));
});
}, []); }, []);
const updateSportId = (sportId: number | null) => { const updateSportId = (sportId: number | null) => {
@@ -65,6 +71,11 @@ export function AppStateProvider({ children }: { children: ReactNode }) {
storage.setOddsSettings(settings); storage.setOddsSettings(settings);
}; };
const updateCardsSettings = (settings: CardsSettings) => {
setState((prev) => ({ ...prev, cardsSettings: settings }));
storage.setCardsSettings(settings);
};
return ( return (
<AppStateContext.Provider <AppStateContext.Provider
value={{ value={{
@@ -74,6 +85,7 @@ export function AppStateProvider({ children }: { children: ReactNode }) {
updateLeagueKey, updateLeagueKey,
updateTimezone, updateTimezone,
updateOddsSettings, updateOddsSettings,
updateCardsSettings,
}} }}
> >
{children} {children}

View File

@@ -32,6 +32,10 @@
"odds_unselected": "Unselected", "odds_unselected": "Unselected",
"odds_modal_title": "Select Bookmakers (Max 2)", "odds_modal_title": "Select Bookmakers (Max 2)",
"odds_confirm": "Confirm", "odds_confirm": "Confirm",
"cards_title": "Cards Settings",
"cards_show": "Show Cards",
"cards_enabled": "On",
"cards_disabled": "Off",
"login": "Login", "login": "Login",
"click_to_login": "Click to login", "click_to_login": "Click to login",
"logout": "Logout", "logout": "Logout",

View File

@@ -32,6 +32,10 @@
"odds_unselected": "未选择", "odds_unselected": "未选择",
"odds_modal_title": "选择赔率公司 (最多2项)", "odds_modal_title": "选择赔率公司 (最多2项)",
"odds_confirm": "确定", "odds_confirm": "确定",
"cards_title": "卡牌设置",
"cards_show": "显示红黄牌",
"cards_enabled": "开启",
"cards_disabled": "关闭",
"login": "登录", "login": "登录",
"click_to_login": "点击登录", "click_to_login": "点击登录",
"logout": "登出", "logout": "登出",

View File

@@ -41,12 +41,12 @@ apiClient.interceptors.request.use(async (config) => {
}); });
const refreshTokenApi = async ( const refreshTokenApi = async (
request: RefreshTokenRequest request: RefreshTokenRequest,
): Promise<RefreshTokenResponse> => { ): Promise<RefreshTokenResponse> => {
try { try {
const response = await apiClient.post<ApiResponse<RefreshTokenResponse>>( const response = await apiClient.post<ApiResponse<RefreshTokenResponse>>(
API_ENDPOINTS.REFRESH_TOKEN, API_ENDPOINTS.REFRESH_TOKEN,
request request,
); );
if (response.data.code === 0) { if (response.data.code === 0) {
@@ -81,13 +81,13 @@ apiClient.interceptors.response.use(
} }
} }
return Promise.reject(error); return Promise.reject(error);
} },
); );
export const fetchSports = async (): Promise<Sport[]> => { export const fetchSports = async (): Promise<Sport[]> => {
try { try {
const response = await apiClient.get<ApiResponse<ApiListResponse<Sport>>>( const response = await apiClient.get<ApiResponse<ApiListResponse<Sport>>>(
API_ENDPOINTS.SPORTS API_ENDPOINTS.SPORTS,
); );
if (response.data.code === 0) { if (response.data.code === 0) {
return response.data.data.list; return response.data.data.list;
@@ -103,7 +103,7 @@ export const fetchSports = async (): Promise<Sport[]> => {
export const fetchCountries = async (): Promise<Country[]> => { export const fetchCountries = async (): Promise<Country[]> => {
try { try {
const response = await apiClient.get<ApiResponse<ApiListResponse<Country>>>( const response = await apiClient.get<ApiResponse<ApiListResponse<Country>>>(
API_ENDPOINTS.COUNTRIES API_ENDPOINTS.COUNTRIES,
); );
if (response.data.code === 0) { if (response.data.code === 0) {
return response.data.data.list; return response.data.data.list;
@@ -127,7 +127,7 @@ export const fetchLeagues = async (params: {
try { try {
const response = await apiClient.get<ApiResponse<ApiListResponse<League>>>( const response = await apiClient.get<ApiResponse<ApiListResponse<League>>>(
API_ENDPOINTS.LEAGUES, API_ENDPOINTS.LEAGUES,
{ params } { params },
); );
if (response.data.code === 0) { if (response.data.code === 0) {
return response.data.data; return response.data.data;
@@ -179,7 +179,7 @@ export const fetchTodayMatches = async (options: {
const response = await apiClient.get<ApiResponse<ApiListResponse<Match>>>( const response = await apiClient.get<ApiResponse<ApiListResponse<Match>>>(
API_ENDPOINTS.MATCHES_TODAY, API_ENDPOINTS.MATCHES_TODAY,
{ params } { params },
); );
if (response.data.code === 0) { if (response.data.code === 0) {
return response.data.data; return response.data.data;
@@ -192,11 +192,11 @@ export const fetchTodayMatches = async (options: {
}; };
export const fetchMatchDetail = async ( export const fetchMatchDetail = async (
id: string id: string,
): Promise<MatchDetailData> => { ): Promise<MatchDetailData> => {
try { try {
const response = await apiClient.get<ApiResponse<MatchDetailData>>( const response = await apiClient.get<ApiResponse<MatchDetailData>>(
API_ENDPOINTS.MATCH_DETAIL(id) API_ENDPOINTS.MATCH_DETAIL(id),
); );
if (response.data.code === 0) { if (response.data.code === 0) {
return response.data.data; return response.data.data;
@@ -211,7 +211,7 @@ export const fetchMatchDetail = async (
export const fetchLiveScore = async ( export const fetchLiveScore = async (
sportId: number, sportId: number,
leagueId?: number, leagueId?: number,
timezone?: string timezone?: string,
): Promise<LiveScoreMatch[]> => { ): Promise<LiveScoreMatch[]> => {
// console.log("Fetching live scores with params:", { // console.log("Fetching live scores with params:", {
// sportId, // sportId,
@@ -234,10 +234,11 @@ export const fetchLiveScore = async (
const response = await apiClient.get<ApiResponse<LiveScoreMatch[]>>( const response = await apiClient.get<ApiResponse<LiveScoreMatch[]>>(
API_ENDPOINTS.LIVESCORE, API_ENDPOINTS.LIVESCORE,
{ params } { params },
); );
if (response.data.code === 0) { if (response.data.code === 0) {
// console.log("Live score data:", JSON.stringify(response.data.data));
return response.data.data; return response.data.data;
} }
@@ -251,7 +252,7 @@ export const fetchLiveScore = async (
export const fetchUpcomingMatches = async ( export const fetchUpcomingMatches = async (
sportId: number, sportId: number,
leagueKey: string, leagueKey: string,
limit: number = 50 limit: number = 50,
): Promise<UpcomingMatch[]> => { ): Promise<UpcomingMatch[]> => {
try { try {
const response = await apiClient.get< const response = await apiClient.get<
@@ -278,7 +279,7 @@ export const fetchUpcomingMatches = async (
// 获取实时赔率(足球/网球使用 LiveOdds篮球/板球使用 Odds // 获取实时赔率(足球/网球使用 LiveOdds篮球/板球使用 Odds
export const fetchOdds = async ( export const fetchOdds = async (
sportId: number, sportId: number,
matchId: number matchId: number,
): Promise<OddsData> => { ): Promise<OddsData> => {
try { try {
const response = await apiClient.get<ApiResponse<OddsData>>( const response = await apiClient.get<ApiResponse<OddsData>>(
@@ -288,7 +289,7 @@ export const fetchOdds = async (
sport_id: sportId, sport_id: sportId,
match_id: matchId, match_id: matchId,
}, },
} },
); );
if (response.data.code === 0) { if (response.data.code === 0) {
@@ -305,7 +306,7 @@ export const fetchOdds = async (
// 搜索联赛、球队或球员 // 搜索联赛、球队或球员
export const fetchSearch = async ( export const fetchSearch = async (
query: string, query: string,
sportId?: number sportId?: number,
): Promise<SearchResult> => { ): Promise<SearchResult> => {
try { try {
const params: { q: string; sportId?: number } = { q: query }; const params: { q: string; sportId?: number } = { q: query };
@@ -315,7 +316,7 @@ export const fetchSearch = async (
const response = await apiClient.get<ApiResponse<SearchResult>>( const response = await apiClient.get<ApiResponse<SearchResult>>(
API_ENDPOINTS.SEARCH, API_ENDPOINTS.SEARCH,
{ params } { params },
); );
if (response.data.code === 0) { if (response.data.code === 0) {
@@ -338,7 +339,7 @@ export const fetchH2H = async (
firstPlayerId?: number; firstPlayerId?: number;
secondPlayerId?: number; secondPlayerId?: number;
timezone?: string; timezone?: string;
} },
): Promise<H2HData> => { ): Promise<H2HData> => {
try { try {
const params: { const params: {
@@ -370,7 +371,7 @@ export const fetchH2H = async (
const response = await apiClient.get<ApiResponse<H2HData>>( const response = await apiClient.get<ApiResponse<H2HData>>(
API_ENDPOINTS.H2H, API_ENDPOINTS.H2H,
{ params } { params },
); );
if (response.data.code === 0) { if (response.data.code === 0) {
@@ -385,12 +386,12 @@ export const fetchH2H = async (
}; };
export const appleSignIn = async ( export const appleSignIn = async (
request: AppleSignInRequest request: AppleSignInRequest,
): Promise<AppleSignInResponse> => { ): Promise<AppleSignInResponse> => {
try { try {
const response = await apiClient.post<ApiResponse<AppleSignInResponse>>( const response = await apiClient.post<ApiResponse<AppleSignInResponse>>(
API_ENDPOINTS.APPLE_SIGNIN, API_ENDPOINTS.APPLE_SIGNIN,
request request,
); );
if (response.data.code === 0) { if (response.data.code === 0) {
@@ -407,7 +408,7 @@ export const appleSignIn = async (
export const logout = async (): Promise<string> => { export const logout = async (): Promise<string> => {
try { try {
const response = await apiClient.post<ApiResponse<string>>( const response = await apiClient.post<ApiResponse<string>>(
API_ENDPOINTS.LOGOUT API_ENDPOINTS.LOGOUT,
); );
if (response.data.code === 0) { if (response.data.code === 0) {
@@ -426,7 +427,7 @@ export const refreshToken = refreshTokenApi;
export const fetchUserProfile = async (): Promise<UserProfile> => { export const fetchUserProfile = async (): Promise<UserProfile> => {
try { try {
const response = await apiClient.get<ApiResponse<UserProfile>>( const response = await apiClient.get<ApiResponse<UserProfile>>(
API_ENDPOINTS.USER_PROFILE API_ENDPOINTS.USER_PROFILE,
); );
if (response.data.code === 0) { if (response.data.code === 0) {
@@ -450,7 +451,7 @@ export const addFavorite = async (request: FavoriteRequest): Promise<any> => {
// console.log("Adding favorite with request:", request); // console.log("Adding favorite with request:", request);
const response = await apiClient.post<ApiResponse<any>>( const response = await apiClient.post<ApiResponse<any>>(
API_ENDPOINTS.FAVORITES, API_ENDPOINTS.FAVORITES,
request request,
); );
if (response.data.code === 0) { if (response.data.code === 0) {
return response.data.data; return response.data.data;
@@ -475,7 +476,7 @@ export const removeFavorite = async (request: {
console.log("Removing favorite with request:", request); console.log("Removing favorite with request:", request);
const response = await apiClient.delete<ApiResponse<any>>( const response = await apiClient.delete<ApiResponse<any>>(
API_ENDPOINTS.FAVORITES, API_ENDPOINTS.FAVORITES,
{ data: request } { data: request },
); );
if (response.data.code === 0) { if (response.data.code === 0) {
return response.data.data; return response.data.data;
@@ -489,14 +490,14 @@ export const removeFavorite = async (request: {
export const checkFavorite = async ( export const checkFavorite = async (
type: string, type: string,
typeId: string typeId: string,
): Promise<FavoriteCheckResponse> => { ): Promise<FavoriteCheckResponse> => {
try { try {
const response = await apiClient.get<ApiResponse<FavoriteCheckResponse>>( const response = await apiClient.get<ApiResponse<FavoriteCheckResponse>>(
API_ENDPOINTS.CHECK_FAVORITE, API_ENDPOINTS.CHECK_FAVORITE,
{ {
params: { type, typeId }, params: { type, typeId },
} },
); );
if (response.data.code === 0) { if (response.data.code === 0) {
return response.data.data; return response.data.data;
@@ -511,14 +512,14 @@ export const checkFavorite = async (
export const fetchFavorites = async ( export const fetchFavorites = async (
type: string, type: string,
page: number = 1, page: number = 1,
pageSize: number = 20 pageSize: number = 20,
): Promise<FavoriteListResponse> => { ): Promise<FavoriteListResponse> => {
try { try {
const response = await apiClient.get<ApiResponse<FavoriteListResponse>>( const response = await apiClient.get<ApiResponse<FavoriteListResponse>>(
API_ENDPOINTS.FAVORITES, API_ENDPOINTS.FAVORITES,
{ {
params: { type, page, pageSize }, params: { type, page, pageSize },
} },
); );
if (response.data.code === 0) { if (response.data.code === 0) {
console.log("Fetched favorites:", JSON.stringify(response.data.data)); console.log("Fetched favorites:", JSON.stringify(response.data.data));

View File

@@ -6,6 +6,7 @@ const STORAGE_KEYS = {
REFRESH_TOKEN: "refresh_token", REFRESH_TOKEN: "refresh_token",
USER: "user", USER: "user",
ODDS_SETTINGS: "odds_settings", ODDS_SETTINGS: "odds_settings",
CARDS_SETTINGS: "cards_settings",
}; };
export interface OddsSettings { export interface OddsSettings {
@@ -13,6 +14,10 @@ export interface OddsSettings {
selectedBookmakers: string[]; selectedBookmakers: string[];
} }
export interface CardsSettings {
enabled: boolean;
}
export const storage = { export const storage = {
async setAccessToken(token: string): Promise<void> { async setAccessToken(token: string): Promise<void> {
await AsyncStorage.setItem(STORAGE_KEYS.ACCESS_TOKEN, token); await AsyncStorage.setItem(STORAGE_KEYS.ACCESS_TOKEN, token);
@@ -61,12 +66,30 @@ export const storage = {
} }
}, },
async setCardsSettings(settings: CardsSettings): Promise<void> {
await AsyncStorage.setItem(
STORAGE_KEYS.CARDS_SETTINGS,
JSON.stringify(settings),
);
},
async getCardsSettings(): Promise<CardsSettings> {
const settingsStr = await AsyncStorage.getItem(STORAGE_KEYS.CARDS_SETTINGS);
if (!settingsStr) return { enabled: false };
try {
return JSON.parse(settingsStr) as CardsSettings;
} catch {
return { enabled: false };
}
},
async clear(): Promise<void> { async clear(): Promise<void> {
await AsyncStorage.multiRemove([ await AsyncStorage.multiRemove([
STORAGE_KEYS.ACCESS_TOKEN, STORAGE_KEYS.ACCESS_TOKEN,
STORAGE_KEYS.REFRESH_TOKEN, STORAGE_KEYS.REFRESH_TOKEN,
STORAGE_KEYS.USER, STORAGE_KEYS.USER,
STORAGE_KEYS.ODDS_SETTINGS, STORAGE_KEYS.ODDS_SETTINGS,
STORAGE_KEYS.CARDS_SETTINGS,
]); ]);
}, },
}; };