10 KiB
10 KiB
Análisis de Mocks de Staff App vs. Schema de Data Connect
Este documento realiza una comparación detallada entre las estructuras de datos (mocks) utilizadas en la aplicación de Staff y las entidades definidas en el schema de GraphQL de Firebase Data Connect. El objetivo es identificar discrepancias, proponer soluciones y asegurar la consistencia entre el frontend y el backend.
1. Perfil de Leaderboard (_profiles)
- Archivo Mock:
lib/screens/worker/worker_profile/level_up/leaderboard_screen.dart - Entidad Data Connect más cercana:
Staff(dataconnect/schema/staff.gql)
Comparación Campo por Campo
| Campo (Mock App) | Campo (Schema GQL Staff) |
Recomendación |
|---|---|---|
id |
id |
✅ Match. |
name |
employeeName |
⚠️ Diferencia de nombre. Renombrar name a employeeName en la app. |
photo_url |
(No existe) |
❌ Campo faltante. El schema de Staff no tiene un campo para URL de foto. Se debe agregar. |
xp |
(No existe) |
❌ Campo faltante. Relacionado con gamificación. Proponer experiencePoints: Int. |
level |
(No existe) |
❌ Campo faltante. Relacionado con gamificación. Proponer level: String. |
user_id |
(No existe) |
⚠️ Diferencia conceptual. El schema Staff tiene vendorId y email. Aclarar si user_id corresponde al id del User o Staff. |
Recomendaciones
-
En la app (Flutter):
- Cambiar el nombre del campo
nameaemployeeNamepara que coincida con el schema.
- Cambiar el nombre del campo
-
En el schema (
staff.gql):- Agregar los campos para la gamificación y el perfil.
type Staff @table(name: "staffs") { # ... campos existentes profilePictureUrl: String experiencePoints: Int @default(expr: "0") level: String }
2. Conversaciones (_conversations)
- Archivo Mock:
lib/screens/worker/worker_profile/support/messages_screen.dart - Entidades Data Connect más cercanas:
Conversation(conversation.gql) yMessage(message.gql).
El mock aplana la información de ambas entidades.
Comparación de Conversation
| Campo (Mock App) | Campo (Schema GQL Conversation) |
Recomendación |
|---|---|---|
sender_id |
participants |
⚠️ Diferencia de estructura. El mock asume una conversación 1-a-1, mientras participants es un String (JSON) con un array de IDs. La app debe adaptarse para manejar múltiples participantes. |
sender_name |
(No existe directamente) | ℹ️ Dato derivado. Este dato debe obtenerse consultando la entidad Staff o User con el ID del participante. |
lastMessage |
(No existe directamente) | ℹ️ Dato derivado. Este debe ser el campo content del último Message asociado a la conversationId. La app debe consultar los mensajes. |
lastTime |
updatedDate |
✅ Match conceptual. updatedDate en Conversation debería actualizarse con cada nuevo mensaje. La app puede usar este campo. |
unread |
(No existe) | ❌ Campo faltante y complejo. El conteo de no leídos es por usuario. El schema actual no lo soporta. El campo readBy en Message podría usarse para calcular esto, pero es ineficiente. Se requiere un rediseño. |
messages |
(Corresponde a la entidad Message) |
ℹ️ Relación. La app debe hacer una query separada para obtener los Message donde conversationId coincida. |
Comparación de Message (anidado en el mock)
| Campo (Mock App) | Campo (Schema GQL Message) |
Recomendación |
|---|---|---|
content |
content |
✅ Match. |
sender_id |
createdBy / senderName |
✅ Match conceptual. El schema tiene createdBy (ID del usuario) y senderName. La app debe usar estos campos. |
Recomendaciones
- En la app (Flutter):
- Adaptar la lógica para manejar
participantscomo un array. - Implementar la obtención de
sender_nameylastMessagea través de queries adicionales. - Eliminar la consulta de mensajes anidada y realizar una consulta separada por
conversationId.
- Adaptar la lógica para manejar
- En el schema (
conversation.gqlymessage.gql):- El manejo de
unreades un desafío. Una solución a largo plazo podría ser una nueva tablaConversationReadStatusque vincule(userId, conversationId, lastReadTimestamp). Por ahora, se puede calcular en el cliente. - El schema actual es funcional pero requiere que el cliente orqueste varias llamadas.
- El manejo de
3. Hojas de Tiempo (_timesheets)
- Archivo Mock:
lib/screens/worker/worker_profile/finances/time_card_screen.dart - Entidades Data Connect más cercanas:
Shift(shift.gql) yEvent(event.gql).
El mock es una vista aplanada que combina información de un turno (Shift) y del evento (Event) al que pertenece.
Comparación Campo por Campo
| Campo (Mock App) | Campo (Schema GQL Shift/Event) |
Recomendación |
|---|---|---|
id |
Shift.id |
✅ Match. |
shift_id |
Shift.id |
✅ Match. (Redundante en el mock). |
date |
Shift.startDate |
✅ Match conceptual. Usar startDate. |
actual_start |
(No existe) | ❌ Campo faltante. El schema de Shift necesita campos para el check-in/out real. Proponer actualStartTime: Timestamp. |
actual_end |
(No existe) | ❌ Campo faltante. Proponer actualEndTime: Timestamp. |
total_hours |
(No existe) | ℹ️ Dato derivado. Debe calcularse en la app o en el backend a partir de actualStartTime y actualEndTime. |
hourly_rate |
Staff.rate / Event.rate? |
⚠️ Requiere clarificación. La tarifa puede depender del staff, del evento o del rol en el turno. El schema de Shift debería tener un campo rate. |
total_pay |
(No existe) | ℹ️ Dato derivado. Calcular total_hours * hourly_rate. |
status |
Shift.status? |
⚠️ Ambigüedad. Shift no tiene status, pero Event sí. El estado del pago (pending, approved, paid) es un concepto diferente. Se necesita un campo paymentStatus en Shift. |
shift_title |
Shift.shiftName |
✅ Match. |
client_name |
Event.clientName o Business.name |
ℹ️ Dato relacionado. Se debe obtener a través del eventId en el Shift para luego consultar el Event o Business asociado. |
location |
Event.eventLocation |
ℹ️ Dato relacionado. Obtener del Event asociado. |
Recomendaciones
-
En la app (Flutter):
- La app debe realizar una consulta que una datos de
Shifty suEventrelacionado para construir esta vista. - Calcular campos derivados como
total_hoursytotal_pay.
- La app debe realizar una consulta que una datos de
-
En el schema (
shift.gql):- Agregar campos cruciales para el registro de tiempo y pago.
type Shift @table(name: "shifts") { # ... campos existentes actualStartTime: Timestamp actualEndTime: Timestamp rate: Float paymentStatus: String # O un enum: PENDING, APPROVED, PAID, DISPUTED }
4. Certificados (_certificates)
- Archivo Mock:
lib/screens/worker/worker_profile/compliance/certificates_screen.dart - Entidad Data Connect más cercana:
Certification(certification.gql)
Comparación Campo por Campo
| Campo (Mock App) | Campo (Schema GQL Certification) |
Recomendación |
|---|---|---|
id |
id |
✅ Match. |
name |
certificationName |
⚠️ Diferencia de nombre. Renombrar name a certificationName en la app. |
icon / color |
(No existe) | ℹ️ Lógica de UI. Estos campos son para la visualización y deben manejarse en el frontend. No pertenecen al schema. |
description |
(No existe) | ❌ Campo faltante. El schema podría beneficiarse de un campo descriptivo. Proponer description: String. |
status |
status y validationStatus |
✅ Match conceptual. El schema tiene dos campos de estado. La app debe combinar o decidir cuál mostrar. CertificationStatus (CURRENT, EXPIRED) parece el correcto. |
expiry |
expiryDate |
✅ Match conceptual. El tipo de dato debe ser consistente (el mock usa String?, el schema String!). |
Recomendaciones
-
En la app (Flutter):
- Cambiar
nameporcertificationName. - Mapear los valores de
statusdel schema al estado que la UI espera.
- Cambiar
-
En el schema (
certification.gql):- Considerar añadir un campo opcional para la descripción.
type Certification @table(name: "certification") { # ... campos existentes description: String }
5. Contactos de Emergencia (_contacts)
- Archivo Mock:
lib/screens/worker/worker_profile/onboarding/emergency_contact_screen.dart - Entidad Data Connect más cercana: Ninguna.
No existe una entidad para almacenar contactos de emergencia.
Recomendaciones
-
En el schema:
- Crear una nueva entidad
EmergencyContact. Debería estar vinculada a unStaff.
# En un nuevo archivo: dataconnect/schema/emergencyContact.gql type EmergencyContact @table(name: "emergency_contacts") { id: UUID! @default(expr: "uuidV4()") staffId: UUID! # FK a la tabla Staff name: String! phone: String! relationship: String # Ejemplo: "Spouse", "Parent", "Friend" createdDate: Timestamp @default(expr: "request.time") updatedDate: Timestamp @default(expr: "request.time") }- Se debe decidir si esta información se almacena como un array de
jsonben la tablaStaffo como una tabla separada. Una tabla separada es más limpia y escalable.
- Crear una nueva entidad
Conclusiones Generales
- Aplanamiento de Datos: La app de Flutter tiende a usar estructuras de datos aplanadas que combinan campos de múltiples entidades de Data Connect. Esto es normal para las vistas de UI, pero requiere que la capa de datos de la app realice las consultas y uniones necesarias.
- Campos Faltantes Críticos: Se han identificado campos faltantes importantes, especialmente en
Shift(para el control de horas y pagos) yStaff(para gamificación y perfil). - Nomenclatura: Hay inconsistencias menores en los nombres de los campos. La recomendación general es alinear la app con los nombres del schema de Data Connect, que es la fuente de verdad.
- Nuevas Entidades: Se necesitan nuevas entidades como
EmergencyContact. Otras estructuras mock (_benefitsData,_attireOptions,_courses, etc.) también requerirán probablemente sus propias tablas y schemas en Data Connect.