diff --git a/resources/openapi.json b/resources/openapi.json index 1c939a6..fa8a918 100644 --- a/resources/openapi.json +++ b/resources/openapi.json @@ -724,6 +724,209 @@ } } }, + "/card-balance-quick-check": { + "get": { + "operationId": "cardBalance.quickCheck", + "summary": "Quick card balance check", + "tags": [ + "Sargytlar - Kart - Kart galyndylary" + ], + "parameters": [ + { + "name": "passport_serie", + "in": "query", + "schema": { + "type": "string", + "enum": [ + "I-AS", + "I-MR", + "II-MR", + "I-AH", + "II-AH", + "I-LB", + "II-LB", + "I-BN", + "II-BN", + "I-DZ", + "II-DZ" + ] + }, + "example": "I-AS" + }, + { + "name": "passport_id", + "in": "query", + "schema": { + "type": "number" + }, + "example": 379514 + }, + { + "name": "card_number", + "in": "query", + "schema": { + "type": "string" + }, + "example": "9934612100000243" + }, + { + "name": "card_month", + "in": "query", + "schema": { + "type": "string", + "enum": [ + "01", + "02", + "03", + "04", + "05", + "06", + "07", + "08", + "09", + "10", + "11", + "12" + ] + }, + "example": "12" + }, + { + "name": "card_year", + "in": "query", + "schema": { + "type": "string", + "enum": [ + "2024", + "2025", + "2026", + "2027", + "2028", + "2029", + "2030", + "2031", + "2032", + "2033", + "2034", + "2035", + "2036", + "2037", + "2038", + "2039", + "2040", + "2041", + "2042", + "2043", + "2044", + "2045", + "2046", + "2047", + "2048", + "2049", + "2050", + "2051", + "2052", + "2053", + "2054", + "2055", + "2056", + "2057", + "2058", + "2059", + "2060", + "2061", + "2062", + "2063", + "2064", + "2065", + "2066", + "2067", + "2068", + "2069", + "2070", + "2071", + "2072", + "2073", + "2074", + "2075", + "2076", + "2077", + "2078", + "2079", + "2080", + "2081", + "2082", + "2083", + "2084", + "2085", + "2086", + "2087", + "2088", + "2089", + "2090" + ] + }, + "example": "2049" + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "anyOf": [ + { + "type": "object", + "properties": { + "status": { + "type": "boolean" + }, + "data": { + "type": "object" + } + }, + "required": [ + "status", + "data" + ] + }, + { + "type": "object", + "properties": { + "status": { + "type": "boolean" + }, + "message": { + "type": "string" + }, + "url": { + "type": "string", + "enum": [ + "" + ] + } + }, + "required": [ + "status", + "message", + "url" + ] + } + ] + } + } + } + }, + "401": { + "$ref": "#/components/responses/AuthenticationException" + }, + "422": { + "$ref": "#/components/responses/ValidationException" + } + } + } + }, "/card-balances": { "get": { "operationId": "cardBalance.index", @@ -6795,6 +6998,9 @@ }, "card_year": { "type": "string" + }, + "card_name": { + "type": "string" } }, "required": [ @@ -6804,7 +7010,8 @@ "passport_id", "card_number", "card_month", - "card_year" + "card_year", + "card_name" ], "title": "ProfileResponse" }, @@ -6947,6 +7154,11 @@ "2090" ], "example": "2049" + }, + "card_name": { + "type": "string", + "example": "Nurmuhammet Allanov", + "maxLength": 255 } }, "required": [ diff --git a/src/screens/Main/HomeScreen.js b/src/screens/Main/HomeScreen.js index 03d58be..264069d 100644 --- a/src/screens/Main/HomeScreen.js +++ b/src/screens/Main/HomeScreen.js @@ -19,6 +19,14 @@ const HomeScreen = () => { const { user, logout } = useAuth(); const [metrics, setMetrics] = useState(null); const [loadingMetrics, setLoadingMetrics] = useState(true); + const [cardBalance, setCardBalance] = useState(null); + const [loadingCardBalance, setLoadingCardBalance] = useState(true); + const [cardBalanceError, setCardBalanceError] = useState(null); + const [isBalanceVisible, setIsBalanceVisible] = useState(true); + + const showBalanceCard = !loadingCardBalance && cardBalanceError === null && cardBalance !== null; + + // (Optional) Add helpers here if needed in the future useEffect(() => { const fetchMetrics = async () => { @@ -39,6 +47,38 @@ const HomeScreen = () => { fetchMetrics(); }, []); + useEffect(() => { + const fetchCardBalance = async () => { + // Ensure user has filled all required card & passport fields + if (!user?.passport_serie || !user?.passport_id || !user?.card_number || !user?.card_month || !user?.card_year) { + setLoadingCardBalance(false); + return; + } + try { + const res = await apiService.getCardBalanceQuickCheck(); + if (res.success) { + // Try common balance keys else fallback to raw + const raw = res.data; + let balanceValue = null; + if (raw && typeof raw === 'object') { + balanceValue = raw.balance ?? raw.card_balance ?? raw.amount ?? null; + } + setCardBalance(balanceValue); + setCardBalanceError(null); + } else { + console.warn('Failed to fetch card balance:', res.error); + setCardBalanceError(res.error || 'Error'); + } + } catch (e) { + console.warn('Error fetching card balance:', e); + } finally { + setLoadingCardBalance(false); + } + }; + + fetchCardBalance(); + }, [user]); + return ( @@ -67,19 +107,25 @@ const HomeScreen = () => { {/* Balance Card */} - - - Jemi balans - - - + {showBalanceCard && ( + + + Jemi balans + setIsBalanceVisible((prev) => !prev)}> + + + + + {isBalanceVisible ? `${cardBalance} TMT` : '•••••'} + + + + {user?.card_number ? `Hasap: ****${String(user.card_number).replace(/[^0-9]/g, '').slice(-4)}` : 'Hasap: ----'} + + + - 1,250.00 TMT - - Hasap: ****1234 - - - + )} ); diff --git a/src/services/apiService.js b/src/services/apiService.js index 36b3667..a804892 100644 --- a/src/services/apiService.js +++ b/src/services/apiService.js @@ -165,6 +165,29 @@ class ApiService { } } + // Quick card balance check + async getCardBalanceQuickCheck(cardNumber = null, cardMonth = null, cardYear = null, passportSerie = null, passportId = null) { + try { + let raw = await authService.getCardBalanceQuickCheck(cardNumber, cardMonth, cardYear, passportSerie, passportId); + + // Handle text response that is JSON-stringified + if (typeof raw === 'string') { + try { raw = JSON.parse(raw); } catch (_) {} + } + + // When API returns { status: false, message: '...' } + if (raw && raw.status === false) { + return { success: false, error: raw.message || 'Failed', data: raw }; + } + + // On success, data may be inside raw.data or raw itself + const data = raw?.data ?? raw; + return { success: true, data }; + } catch (error) { + return { success: false, error: error.message }; + } + } + // ================================ // Loan Paid-Off Letter Orders // ================================ diff --git a/src/services/authService.js b/src/services/authService.js index d04fc5e..b3b6e60 100644 --- a/src/services/authService.js +++ b/src/services/authService.js @@ -370,6 +370,47 @@ class AuthService { const query = `start_date=${encodeURIComponent(startDate)}&end_date=${encodeURIComponent(endDate)}`; return this.makeRequest(`/card-transactions-download/${orderId}?${query}`, null, true, 'GET'); } + + // ================================ + // Card balance quick check (Kart galyndysy) + // ================================ + + async getCardBalanceQuickCheck(cardNumber = null, cardMonth = null, cardYear = null, passportSerie = null, passportId = null) { + // Fallback to stored user profile for missing fields + let serie = passportSerie; + let pid = passportId; + let cNumber = cardNumber; + let cMonth = cardMonth; + let cYear = cardYear; + + if (!serie || !pid || !cNumber || !cMonth || !cYear) { + const user = await this.getStoredUser(); + serie = serie || user?.passport_serie; + pid = pid || user?.passport_id; + cNumber = cNumber || user?.card_number; + cMonth = cMonth || user?.card_month; + cYear = cYear || user?.card_year; + } + + if (!serie || !pid || !cNumber || !cMonth || !cYear) { + throw new Error('Card or passport details are missing'); + } + + // Ensure values are properly formatted + const plainCardNumber = String(cNumber).replace(/[^0-9]/g, '').slice(0, 16); + const monthStr = String(cMonth).padStart(2, '0'); + + const payload = { + passport_serie: serie, + passport_id: pid, + card_number: plainCardNumber, + card_month: monthStr, + card_year: String(cYear), + }; + + // POST request – authenticated (token header will be included if available) + return this.makeRequest('/card-balance-quick-check', payload, true, 'POST'); + } } export default new AuthService(); \ No newline at end of file