@sudobility/sudojo_lib 0.0.88 → 0.0.89
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useDailyGame.d.ts","sourceRoot":"","sources":["../../src/hooks/useDailyGame.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,0BAA0B,CAAC;AACtD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAEvD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"useDailyGame.d.ts","sourceRoot":"","sources":["../../src/hooks/useDailyGame.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,0BAA0B,CAAC;AACtD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAEvD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAgEtD,MAAM,WAAW,mBAAmB;IAClC,mCAAmC;IACnC,aAAa,EAAE,aAAa,CAAC;IAC7B,kCAAkC;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,sCAAsC;IACtC,KAAK,EAAE,MAAM,CAAC;IACd,+CAA+C;IAC/C,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,kCAAkC;IAClC,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,kBAAkB;IACjC,2BAA2B;IAC3B,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,kDAAkD;IAClD,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,uCAAuC;IACvC,MAAM,EAAE,eAAe,CAAC;IACxB,8BAA8B;IAC9B,SAAS,EAAE,OAAO,CAAC;IACnB,4BAA4B;IAC5B,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,+BAA+B;IAC/B,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,mBAAmB,GAAG,kBAAkB,CA0E7E"}
|
|
@@ -3,7 +3,15 @@
|
|
|
3
3
|
* Handles auth and subscription status with automatic refresh
|
|
4
4
|
*/
|
|
5
5
|
import { useEffect, useMemo, useRef } from 'react';
|
|
6
|
-
import {
|
|
6
|
+
import { useSudojoDailyByDate } from '@sudobility/sudojo_client';
|
|
7
|
+
/** Get today's date in local timezone as YYYY-MM-DD */
|
|
8
|
+
function getLocalDateString() {
|
|
9
|
+
const now = new Date();
|
|
10
|
+
const year = now.getFullYear();
|
|
11
|
+
const month = String(now.getMonth() + 1).padStart(2, '0');
|
|
12
|
+
const day = String(now.getDate()).padStart(2, '0');
|
|
13
|
+
return `${year}-${month}-${day}`;
|
|
14
|
+
}
|
|
7
15
|
/** Check if response indicates auth is required */
|
|
8
16
|
function isAuthRequired(response, error) {
|
|
9
17
|
if (response?.success === false &&
|
|
@@ -67,9 +75,8 @@ export function useDailyGame(options) {
|
|
|
67
75
|
authToken: token,
|
|
68
76
|
subscriptionActive,
|
|
69
77
|
});
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
const { data, isLoading, error, refetch } = useSudojoTodayDaily(networkClient, baseUrl, token);
|
|
78
|
+
const todayDate = useMemo(() => getLocalDateString(), []);
|
|
79
|
+
const { data, isLoading, error, refetch } = useSudojoDailyByDate(networkClient, baseUrl, token, todayDate);
|
|
73
80
|
// Determine status based on response
|
|
74
81
|
const status = useMemo(() => {
|
|
75
82
|
if (isLoading)
|
|
@@ -92,8 +99,11 @@ export function useDailyGame(options) {
|
|
|
92
99
|
}, [data]);
|
|
93
100
|
const dailyDate = useMemo(() => {
|
|
94
101
|
if (daily?.date) {
|
|
95
|
-
const
|
|
96
|
-
|
|
102
|
+
const d = new Date(daily.date);
|
|
103
|
+
const year = d.getFullYear();
|
|
104
|
+
const month = String(d.getMonth() + 1).padStart(2, '0');
|
|
105
|
+
const day = String(d.getDate()).padStart(2, '0');
|
|
106
|
+
return `${year}-${month}-${day}`;
|
|
97
107
|
}
|
|
98
108
|
return null;
|
|
99
109
|
}, [daily]);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useDailyGame.js","sourceRoot":"","sources":["../../src/hooks/useDailyGame.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC;AAGnD,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"useDailyGame.js","sourceRoot":"","sources":["../../src/hooks/useDailyGame.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Hook for fetching and managing today's daily puzzle\n * Handles auth and subscription status with automatic refresh\n */\n\nimport { useEffect, useMemo, useRef } from 'react';\nimport type { Daily } from '@sudobility/sudojo_types';\nimport type { NetworkClient } from '@sudobility/types';\nimport { useSudojoDailyByDate } from '@sudobility/sudojo_client';\nimport type { GameFetchStatus } from './useLevelGame';\n\n/** Get today's date in local timezone as YYYY-MM-DD */\nfunction getLocalDateString(): string {\n const now = new Date();\n const year = now.getFullYear();\n const month = String(now.getMonth() + 1).padStart(2, '0');\n const day = String(now.getDate()).padStart(2, '0');\n return `${year}-${month}-${day}`;\n}\n\n/** Extended API response with action field from Sudojo API */\ninterface SudojoApiResponse<T> {\n success: boolean;\n data?: T;\n error?: string | null | undefined;\n message?: string;\n action?: {\n type: string;\n options?: string[];\n };\n}\n\n/** Check if response indicates auth is required */\nfunction isAuthRequired(\n response: SudojoApiResponse<unknown> | undefined,\n error: unknown\n): boolean {\n if (\n response?.success === false &&\n response.action?.type === 'auth_required'\n ) {\n return true;\n }\n if (error && typeof error === 'object') {\n const err = error as { message?: string };\n if (err.message?.includes('Account required')) return true;\n }\n return false;\n}\n\n/** Check if response indicates subscription is required */\nfunction isSubscriptionRequired(\n response: SudojoApiResponse<unknown> | undefined,\n error: unknown\n): boolean {\n if (\n response?.success === false &&\n response.action?.type === 'subscription_required'\n ) {\n return true;\n }\n if (error && typeof error === 'object') {\n const err = error as { message?: string };\n if (\n err.message?.includes('Daily limit reached') ||\n err.message?.includes('subscription')\n ) {\n return true;\n }\n }\n return false;\n}\n\nexport interface UseDailyGameOptions {\n /** Network client for API calls */\n networkClient: NetworkClient;\n /** Base URL for the Sudojo API */\n baseUrl: string;\n /** Access token for authentication */\n token: string;\n /** Whether subscription is currently active */\n subscriptionActive?: boolean;\n /** Whether to enable the query */\n enabled?: boolean;\n}\n\nexport interface UseDailyGameResult {\n /** Today's daily puzzle */\n daily: Daily | null;\n /** The date string for this daily (YYYY-MM-DD) */\n dailyDate: string | null;\n /** Current status of the game fetch */\n status: GameFetchStatus;\n /** Whether data is loading */\n isLoading: boolean;\n /** Error if fetch failed */\n error: Error | null;\n /** Refetch the daily puzzle */\n refetch: () => void;\n}\n\n/**\n * Hook for fetching today's daily puzzle\n *\n * Automatically refetches when auth token or subscription status changes.\n * Returns status indicating whether auth or subscription is required.\n *\n * @param options - Hook options\n * @returns Daily puzzle data and status\n *\n * @example\n * ```tsx\n * function DailyPage() {\n * const { daily, dailyDate, status, refetch } = useDailyGame({\n * networkClient,\n * config,\n * auth,\n * subscriptionActive: subscription.isActive,\n * });\n *\n * if (status === 'loading') return <Loading />;\n * if (status === 'auth_required') return <AuthRequired onLogin={openAuthModal} />;\n * if (status === 'subscription_required') return <SubscriptionPaywall onSuccess={refetch} />;\n * if (status === 'error') return <Error />;\n *\n * return <SudokuGame puzzle={daily.board} solution={daily.solution} />;\n * }\n * ```\n */\nexport function useDailyGame(options: UseDailyGameOptions): UseDailyGameResult {\n const {\n networkClient,\n baseUrl,\n token,\n subscriptionActive = false,\n enabled: _enabled = true,\n } = options;\n\n // Track previous state to detect changes\n const prevStateRef = useRef({\n authToken: token,\n subscriptionActive,\n });\n\n const todayDate = useMemo(() => getLocalDateString(), []);\n\n const { data, isLoading, error, refetch } = useSudojoDailyByDate(\n networkClient,\n baseUrl,\n token,\n todayDate\n );\n\n // Determine status based on response\n const status = useMemo((): GameFetchStatus => {\n if (isLoading) return 'loading';\n if (isAuthRequired(data, error)) return 'auth_required';\n if (isSubscriptionRequired(data, error)) return 'subscription_required';\n if (error) return 'error';\n if (data?.success && data.data) return 'success';\n return 'loading';\n }, [isLoading, data, error]);\n\n const daily = useMemo(() => {\n if (data?.success && data.data) {\n return data.data;\n }\n return null;\n }, [data]);\n\n const dailyDate = useMemo((): string | null => {\n if (daily?.date) {\n const d = new Date(daily.date);\n const year = d.getFullYear();\n const month = String(d.getMonth() + 1).padStart(2, '0');\n const day = String(d.getDate()).padStart(2, '0');\n return `${year}-${month}-${day}`;\n }\n return null;\n }, [daily]);\n\n // Auto-refresh when auth token or subscription status changes\n useEffect(() => {\n const prev = prevStateRef.current;\n const authChanged = prev.authToken !== token;\n const subscriptionChanged = !prev.subscriptionActive && subscriptionActive;\n\n if (authChanged || subscriptionChanged) {\n refetch();\n }\n\n // Update ref for next comparison\n prevStateRef.current = { authToken: token, subscriptionActive };\n }, [token, subscriptionActive, refetch]);\n\n return {\n daily,\n dailyDate,\n status,\n isLoading,\n error: error ?? (data?.error ? new Error(data.error) : null),\n refetch: () => refetch(),\n };\n}\n"]}
|