Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
8bfeee7
Fixes del sprint 5 para el checkout
Mvjtb May 14, 2025
443d8a1
Add order status handling and websocket integration for real-time upd…
Mvjtb May 16, 2025
40e7bd5
Refactor useOrderSocket to enhance authorization handling and improve…
Mvjtb May 16, 2025
6e0bb77
Refactor useOrderSocket to improve code clarity and enhance authoriza…
Mvjtb May 16, 2025
559955b
Update @pharmatech/sdk to version 0.4.18 and add paymentMethod to Che…
Mvjtb May 17, 2025
cc8fdfb
Update CheckoutScreen to integrate paymentMethod with SDK and refacto…
Mvjtb May 17, 2025
2ca4c65
Refactor useOrderSocket to improve token handling, add event logging,…
Mvjtb May 17, 2025
06f9ba1
Remove unnecessary comment in useOrderSocket and add a blank line in …
Mvjtb May 17, 2025
09dc66e
Refactor useOrderSocket to improve readability and memoization of ord…
Mvjtb May 17, 2025
b17cd0c
CheckoutScreen to use updated CreateOrder type and remove unused paym…
Mvjtb May 17, 2025
3ada79b
Refactor useOrderSocket to enhance order handling with initial order …
Mvjtb May 17, 2025
59a5e11
Update @pharmatech/sdk to version 0.4.19; refactor CheckoutScreen to …
Mvjtb May 21, 2025
b301ea5
Refactor PaymentInformationService.findAll to return response directl…
Mvjtb May 21, 2025
c2ec3cd
Merge branch 'dev' into fix/sprint-5-checkout
Mvjtb May 21, 2025
93f8dfa
PaymentConfirmation interface to include the orderId
Mvjtb May 24, 2025
9e3a42a
Add payment method handling in CheckoutScreen
Mvjtb May 24, 2025
f1ed70a
Add InProgressOrder screen and update Checkout flow for order tracking
Mvjtb May 24, 2025
773121d
Refactor Checkout and InProgressOrder screens to streamline order han…
Mvjtb May 24, 2025
8249357
Update InProgressOrderScreen to skip step 2 for CARD and CASH payment…
Mvjtb May 24, 2025
057ab04
Refactor InProgressOrderScreen, integrate order updates via WebSocket
Mvjtb May 24, 2025
093183d
Remove unused order status utility file
Mvjtb May 24, 2025
a8cbb49
Add validation popup and refactor InProgressOrderScreen for payment f…
Mvjtb May 24, 2025
ddfdef4
Refactor WebSocket
Mvjtb May 25, 2025
a94dcf6
Implement WebSocket InProgressOrderScreen for real-time order updates
Mvjtb May 26, 2025
7edc5f7
Refactor InProgressOrderScreen to utilize centralized WebSocket manag…
Mvjtb May 28, 2025
dcfacba
Changing the socket structure
Mvjtb May 29, 2025
dc0f7fa
Add pull-to-refresh functionality
Mvjtb May 29, 2025
15e102b
Add loading indicator for payment processing in InProgressOrderScreen
Mvjtb May 29, 2025
012d171
Adapting to latest sdk
IglesiasMiguel May 29, 2025
4631cd3
Merge branch 'fix/sprint-5-checkout' of https://github.com/PharmaTech…
IglesiasMiguel May 29, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,14 @@
},
"dependencies": {
"@expo-google-fonts/poppins": "^0.2.3",
"@pharmatech/sdk": "^0.4.11",
"@pharmatech/sdk": "^0.4.21",
"@ptomasroos/react-native-multi-slider": "^2.2.2",
"@react-native-community/slider": "^4.5.6",
"@reduxjs/toolkit": "^2.6.1",
"date-fns": "^4.1.0",
"expo": "~52.0.37",
"expo-constants": "~17.0.7",
"expo-dev-client": "~5.0.20",
"expo-font": "~13.0.4",
"expo-image-picker": "~16.0.6",
"expo-linking": "~7.0.5",
Expand All @@ -51,8 +52,7 @@
"react-native-svg": "^15.11.2",
"react-redux": "^9.2.0",
"socket.io-client": "^4.8.1",
"tailwindcss": "^3.4.17",
"expo-dev-client": "~5.0.20"
"tailwindcss": "^3.4.17"
},
"devDependencies": {
"@babel/core": "^7.25.2",
Expand Down
21 changes: 21 additions & 0 deletions src/app/_layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,27 @@ export default function RootLayout() {
/>
<Stack.Screen
name="checkout"
options={({ navigation }) => ({
headerTitle: '',
headerTransparent: true,
headerShown: true,
headerLeft: () => (
<TouchableOpacity
onPress={() => navigation.goBack()}
style={{
padding: 12,
marginLeft: -12,
flexDirection: 'row',
alignItems: 'center',
}}
>
<ChevronLeftIcon width={28} height={28} color="#000" />
</TouchableOpacity>
),
})}
/>
<Stack.Screen
name="in-progress-order"
options={{
headerTitle: '',
headerTransparent: true,
Expand Down
3 changes: 3 additions & 0 deletions src/app/in-progress-order.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import InProgressOrderScreen from '../screens/InProgressOrderScreen';

export default InProgressOrderScreen;
46 changes: 26 additions & 20 deletions src/components/PaymentInfoForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,7 @@ import Dropdown from './Dropdown';
import { PharmaTech } from '@pharmatech/sdk';

interface Props {
paymentMethod:
| 'punto_de_venta'
| 'efectivo'
| 'transferencia'
| 'pago_movil'
| null;
paymentMethod: 'CARD' | 'CASH' | 'BANK_TRANSFER' | 'MOBILE_PAYMENT' | null;
total: string;
onValidationChange: (isValid: boolean) => void;
onBankChange: (value: string) => void;
Expand Down Expand Up @@ -90,11 +85,14 @@ const PaymentInfoForm: React.FC<Props> = ({
useEffect(() => {
const isValid =
paymentMethod !== null &&
(paymentMethod === 'pago_movil' || paymentMethod === 'transferencia')
(paymentMethod === 'MOBILE_PAYMENT' || paymentMethod === 'BANK_TRANSFER')
? bank.trim() !== '' &&
/^\d+$/.test(reference) &&
/^\d{4,}$/.test(reference) &&
reference.trim() !== '' &&
/^\d{1,8}$/.test(documentNumber) &&
!/^0+$/.test(reference) &&
/^\d{7,8}$/.test(documentNumber) &&
!/^0+$/.test(documentNumber) &&
!/^0/.test(documentNumber) &&
/^\d{11}$/.test(phone)
: true;

Expand Down Expand Up @@ -129,8 +127,8 @@ const PaymentInfoForm: React.FC<Props> = ({

return (
<View style={styles.container}>
{(paymentMethod === 'pago_movil' ||
paymentMethod === 'transferencia') && (
{(paymentMethod === 'MOBILE_PAYMENT' ||
paymentMethod === 'BANK_TRANSFER') && (
<>
<PoppinsText style={styles.label}>
Realiza el pago en la siguiente cuenta de Pharmatech
Expand All @@ -155,7 +153,7 @@ const PaymentInfoForm: React.FC<Props> = ({

<View style={styles.row}>
<View style={[styles.inputWrapper, styles.largeInput]}>
{paymentMethod === 'pago_movil' ? (
{paymentMethod === 'MOBILE_PAYMENT' ? (
<Input
label="Teléfono"
value="0414-1234567"
Expand Down Expand Up @@ -208,9 +206,11 @@ const PaymentInfoForm: React.FC<Props> = ({
placeholder="Ingrese la referencia"
getValue={handleReferenceChange}
fieldType="number"
errorText="Debe ser un número válido"
validation={(val) => /^\d+$/.test(val) && val.trim() !== ''}
showIcon
errorText="Debe ser un número valido"
validation={(val) =>
/^\d{4,}$/.test(val) && val.trim() !== '' && !/^0+$/.test(val)
}
showIcon={reference.length > 0}
useDefaultValidation={false}
{...editableInputProps}
/>
Expand All @@ -220,9 +220,14 @@ const PaymentInfoForm: React.FC<Props> = ({
value={documentNumber}
getValue={handleDocumentNumberChange}
fieldType="number"
errorText="El campo no debe estar vacío"
validation={(val) => /^\d+$/.test(val) && val.trim() !== ''}
showIcon
errorText="Debe ser un número de documento valido"
validation={(val) =>
/^\d{7,8}$/.test(val) &&
val.trim() !== '' &&
!/^0+$/.test(val) &&
!/^0/.test(val)
}
showIcon={documentNumber.length > 0}
useDefaultValidation={false}
{...editableInputProps}
/>
Expand All @@ -233,13 +238,14 @@ const PaymentInfoForm: React.FC<Props> = ({
getValue={handlePhoneChange}
fieldType="number"
errorText="Debe tener exactamente 11 dígitos"
validation={(val) => /^\d{11}$/.test(val)}
showIcon
validation={(val) => /^\d{11}$/.test(val) && !/^0+$/.test(val)}
showIcon={phone.length > 0}
useDefaultValidation={false}
{...editableInputProps}
/>
</>
)}
{/* Si se requiere mostrar algo para CASH o CARD, agregar aquí */}
</View>
);
};
Expand Down
94 changes: 74 additions & 20 deletions src/components/PaymentStatusMessage.tsx
Original file line number Diff line number Diff line change
@@ -1,44 +1,98 @@
import React from 'react';
import { CheckCircleIcon, XCircleIcon } from 'react-native-heroicons/outline';
import {
CheckCircleIcon,
XCircleIcon,
ClockIcon,
} from 'react-native-heroicons/outline';
import theme from '../styles/theme';
import { Text, View, StyleSheet } from 'react-native';

type OrderStatus =
| 'requested'
| 'approved'
| 'ready_for_pickup'
| 'in_progress'
| 'canceled'
| 'completed';

interface PaymentStatusMessageProps {
status: 'approved' | 'rejected';
orderStatus: OrderStatus;
orderNumber: string;
userName: string;
}

const statusConfig: Record<
OrderStatus,
{
icon: React.ElementType;
color: string;
title: string;
message: (orderNumber: string, userName: string) => string;
}
> = {
requested: {
icon: ClockIcon,
color: theme.Colors.semanticWarning,
title: 'Orden en espera',
message: () =>
`Estamos procesando tu orden. En un momento actualizaremos el estado de tu orden. Si tienes alguna duda, por favor contacta a nuestro equipo de soporte.`,
},
approved: {
icon: CheckCircleIcon,
color: theme.Colors.semanticSuccess,
title: 'Orden aprobada',
message: (_orderNumber, userName) =>
`¡Gracias por tu compra, ${userName}! Tu orden ha sido aprobada.`,
},
ready_for_pickup: {
icon: CheckCircleIcon,
color: theme.Colors.semanticSuccess,
title: 'Lista para recoger',
message: () =>
'Tu pedido está listo para ser recogido en la sucursal seleccionada.',
},
in_progress: {
icon: ClockIcon,
color: theme.Colors.semanticWarning,
title: 'Orden en progreso',
message: () =>
'Tu pedido está en progreso. Pronto comenzaremos a procesarlo.',
},
canceled: {
icon: XCircleIcon,
color: theme.Colors.semanticDanger,
title: 'Orden rechazada',
message: () =>
'No pudimos procesar tu orden. Lamentamos informarte que hubo un problema al generar tu pedido.',
},
completed: {
icon: CheckCircleIcon,
color: theme.Colors.semanticSuccess,
title: 'Orden completada',
message: (_orderNumber, userName) =>
`¡Gracias por tu compra, ${userName}! Tu orden ha sido completada exitosamente.`,
},
};

const PaymentStatusMessage: React.FC<PaymentStatusMessageProps> = ({
status,
orderStatus,
orderNumber,
userName,
}) => {
const config = statusConfig[orderStatus] || statusConfig['requested'];
const Icon = config.icon;

return (
<View style={styles.container}>
<View style={styles.iconContainer}>
{status === 'approved' ? (
<CheckCircleIcon
width={30}
height={30}
color={theme.Colors.semanticSuccess}
/>
) : (
<XCircleIcon
width={30}
height={30}
color={theme.Colors.semanticDanger}
/>
)}
<Icon width={30} height={30} color={config.color} />
</View>
<View style={styles.textContainer}>
<Text style={[styles.title, { color: theme.Colors.textMain }]}>
Orden #{orderNumber}
{config.title} #{orderNumber}
</Text>
<Text style={[styles.message, { color: theme.Colors.textLowContrast }]}>
{status === 'approved'
? `¡Gracias por tu compra, ${userName}!`
: 'No pudimos procesar tu orden. Lamentamos informarte que hubo un problema al generar tu pedido.'}
{config.message(orderNumber, userName)}
</Text>
</View>
</View>
Expand Down
52 changes: 52 additions & 0 deletions src/lib/deliverySocket/deliverySocket.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import io, { Socket } from 'socket.io-client';
import { SOCKET_URL } from '../socketUrl';
import * as SecureStore from 'expo-secure-store';

let socket: Socket | null = null;

export const initializeSocket = async (): Promise<Socket> => {
if (socket) return socket;

const token = await SecureStore.getItemAsync('auth_token');
if (!token) {
console.error('Token de autenticación no encontrado');
throw new Error('Token de autenticación no encontrado');
}

console.log('Inicializando WebSocket con URL:', SOCKET_URL);
console.log('Enviando token JWT:', token);

socket = io(SOCKET_URL, {
autoConnect: false,
transports: ['polling'], // Asegurarnos de que ambos transportes estén habilitados
transportOptions: {
polling: {
extraHeaders: {
Authorization: `Bearer ${token}`,
},
},
},
});

socket.on('connect', () => {
console.log('WebSocket conectado exitosamente');
});

socket.on('connect_error', (error) => {
console.error('Error de conexión al WebSocket:', error);
});

socket.on('disconnect', (reason) => {
console.warn('WebSocket desconectado. Razón:', reason);
});

return socket;
};

export const disconnectSocket = () => {
if (socket) {
console.log('Desconectando WebSocket');
socket.disconnect();
socket = null;
}
};
5 changes: 3 additions & 2 deletions src/lib/socketUrl.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
const devModeFlag = process.env.PHARMATECH_DEV_MODE === 'true';
const devUrl = 'ws://api-dev-8jfx.onrender.com';
const prodUrl = 'ws://api-d8h5.onrender.com';

const devUrl = 'https://api-dev-8jfx.onrender.com';
const prodUrl = 'https://api-d8h5.onrender.com';

export const SOCKET_URL = devModeFlag ? devUrl : prodUrl;
Loading
Loading