Commit Graph
69 Commits
Author SHA1 Message Date
Lizandro GuarnizoandClaude Opus 5 7930890d09 fix: clients read the professional's real agenda, not their own
/services/public-calendar/{professionalId} exists after all — the web has been
using it all along. My earlier probes missed it because they guessed the URL
shape, and because it is keyed by the professionals row id rather than the
owning user id, which ProfessionalEntity was discarding.

Adds ProfessionalEntity.recordId and points the client calendar at the public
endpoint. Until now a client browsing a professional's availability was served
their own agenda, so every slot looked free and two people could book the same
hour. A failed load now hides the slots and offers a retry instead of showing
them as available.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-24 21:29:31 -05:00
Lizandro GuarnizoandClaude Opus 5 389f876cfa fix: repair the booking flow end to end
ci-651288 / run (push) Waiting to run
ci-946620 / run (push) Waiting to run
Verified the real contracts against the backend before changing anything.

Chat (three defects, one root cause):
- every chat endpoint is keyed by the chat id, not the service id. The app
  called POST /chat/start, threw away the id it returned and kept using the
  service id, so every later request 404'd.
- messages arrive as {data, meta}; reading the body as a bare list threw and
  surfaced as an empty conversation.
- the bloc created the chat and then never emitted ChatLoaded (the else hung
  off `if (chat == null)`), leaving a permanent spinner. Sending a message
  emitted nothing at all, so it vanished until reopening.
Messages now render optimistically and roll back if the send fails, and the
screen distinguishes "loading" from "could not open" with a retry.

Appointments:
- a null range1_hour2 parsed as 00:00, so new appointments were born
  "Caducado" and every action was hidden. It now falls back to the start time.
- service requests validate the HTTP status and tolerate an empty body: a 4xx
  was treated as success and a 204 as failure.
- creating a service with no id in the response no longer reports success and
  navigates to a service that does not exist.
- dispatching LoadService from build() looped forever on failure; the three
  detail screens now load once and offer a retry.

Ratings:
- both sides read userScored, so only one of the two could ever rate. The
  client side now reads professionalScored.
- the screen closed before the request finished, killing the provider mid
  flight while addComment swallowed every error. It now waits for confirmation.
- score/reputation parsing tolerates integers and numeric strings instead of
  emptying the review list.

Also: guarded map lookups in ScoreBloc, a nullable name in the search list,
and error states with retry where a failure used to shimmer forever.

Verified against the backend: `accepted` is the status the API expects, so the
suspected spelling bug was a false alarm and was left alone.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-24 20:47:54 -05:00
Lizandro GuarnizoandClaude Opus 5 8c6e2ae024 fix: compare service days as dates, not raw strings
DateTime.toString() renders "2026-07-13 00:00:00.000Z" while the backend
sends "2026-07-13T00:00:00.000Z", so every day comparison was false and no
booked slot was ever detected. Both calendars showed fully free days.

The client calendar now also treats an unloaded agenda as busy instead of
free: rendering a taken slot as available leads straight to a double booking.

Note: the client still reads /services/professional/calendar, which returns
the *caller's* calendar. There is no endpoint for another professional's
agenda, so a client cannot yet see which of that professional's slots are
taken. That needs a backend endpoint.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-24 20:27:40 -05:00
Lizandro GuarnizoandClaude Opus 5 2c1ba7f6d5 fix(calendar): distinguish blocked slots from booked ones
ci-651288 / run (push) Waiting to run
ci-946620 / run (push) Waiting to run
_isOccupied matched any service on the slot regardless of status. Unblocking
sets the service to cancelled, so a released slot still rendered as occupied
and the unblock looked like it did nothing. Cancelled and denied services are
now ignored, and self-booked slots get their own "Bloqueado" state with a
release action, mirroring the web.

Self-booking now spans the professional's configured slot duration instead of
a hardcoded two hours, which no longer matched the generated slots.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-24 16:50:57 -05:00
Lizandro GuarnizoandClaude Opus 5 30b8689814 chore: sync generated plugin registrants after Firebase package removal
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-24 16:46:04 -05:00
Lizandro GuarnizoandClaude Opus 5 8631e6f729 fix: port 7 web features and repair the endless-loading screens
Root cause behind most "stuck loading" reports: the backend changed shape
(schedules became an array, location_preferences a string) while the mobile
parser still hard-cast to Map/int. The TypeError was swallowed by a silent
catch that returned null, and screens only handled the success state, so a
parse failure rendered as a permanent spinner. Same class of bug appeared
across service lists via non-null map lookups and a total absence of
request timeouts.

Ported from prosappweb:
- in-app suggestions (POST /suggestions)
- policies/terms from GET /settings/policies
- configurable appointment length (slot_duration_minutes)
- block/unblock calendar slots (POST /services/block)
- GPS city detection on the profile (Nominatim)
- server-side professional search with haversine distance
- retry cooldown after a rejected professional application

Reliability:
- parse schedules array (day_of_week 0=Mon) and string location_preferences
- read times as wall clock, so 08:00 stays 08:00 across timezones
- carry minutes into hours in TimeOfDay.add; a minute-based step used to
  loop forever and freeze the calendar (covered by test/time_slots_test.dart)
- semver update check instead of string equality, which blocked every build
  that did not exactly match the configured version
- request timeouts across all repositories
- surface HTTP >= 400 instead of reporting failed writes as success
- error states with retry instead of an indefinite shimmer

Includes pre-existing uncommitted work from the UI redesign.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-24 16:45:42 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 06a89df690 feat(ui): apply card design to all service list screens
ci-651288 / run (push) Has been cancelled
ci-946620 / run (push) Has been cancelled
Port the same card UI pattern from the redesigned solicitudes screen
to the 4 remaining list screens (pro/user active services + history):

- 4px colored left strip matching service status color
- Circular avatar with status-colored border + letter fallback
- Status badge with icon + colored border (replaces solid filled badges)
- Date/time row with calendar icon
- Theme-aware colors via _Th extension (respects dark/light mode)
- AppBar with brand blue (replaces default grey)
- Empty state with icon + descriptive text
- Shimmer placeholders as rounded cards (replaces ListTile shimmer)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-30 22:46:10 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 a65e671603 feat(ui): port web UI/UX improvements to mobile app
Port the 3 redesigned views from prosappweb to prosappco:

- Solicitudes: modern cards with 4px colored left strip, status badge with
  icon+border, avatar with status-colored ring, date/time row, empty state
- Calendario: card-wrapped TableCalendar with custom CalendarStyle (blue
  selected/ring today), day header card with date box + occupied/available
  stat pills, slot cards with colored strip and time badge instead of
  gradient circles
- Perfil profesional: gradient banner header with profession pill + camera
  overlay, section cards with icon+title, payment method chips (animated)
  instead of checkboxes, schedule rows with colored active/inactive dots,
  theme-aware colors throughout (respects dark/light mode)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-30 22:38:55 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 1e962af6e8 feat: redesign professional pending and denied screens
- professional_denied_screen: full UI with icon, bullet list of next steps,
  re-register button and logout option (was just a Text widget)
- professional_pending_screen: replace static GIF screen with step-by-step
  progress indicator (submitted → in review → approved), notification tip,
  logout button

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-25 16:06:35 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 2c5b237890 feat: SMS OTP phone auth + mandatory phone verification gate
- MyUser: add isPhoneVerified field (from is_phone_verified in API)
- ApiUserRepository: signInWithPhoneNumber calls POST /auth/send-otp,
  verifyOTP calls POST /auth/phone, linkWithOTP calls POST /auth/verify-phone
  Added updateFcmToken and changePassword methods
- AuthBloc: remove Firebase PhoneVerificationService, use repository OTP flow
- app_view.dart: gate authenticated users without verified phone to
  PhoneVerifyRequiredScreen before showing HomeScreen
- welcome_screen.dart: full redesign with gradient header, logo, integrated
  OTP flow (phone → code in same screen), 60s resend timer
- PhoneVerifyRequiredScreen: new screen for users who need to verify phone

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-25 15:53:43 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 38beca4b4f feat: implement SMS OTP auth via backend API
- signInWithPhoneNumber: calls POST /auth/send-otp, stores pending phone
- verifyOTP: calls POST /auth/phone with phone+code, saves token
- linkWithOTP: calls POST /auth/verify-phone (authenticated) with phone+code
- AuthBloc._linkWithPhoneNumber: replaced Firebase PhoneVerificationService with repository call

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-25 15:23:39 -05:00
Lizandro Guarnizo 7446f22e23 update 2026-06-18 21:41:35 -05:00
Lizandro Guarnizo a24bbe6fc6 update 2026-06-18 18:16:50 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 79f350e85f feat: implement FCM push notifications via firebase_messaging
- Add firebase_core + firebase_messaging to pubspec.yaml
- Initialize Firebase in main.dart before runApp
- NotificationBloc: request permission, get FCM token, register with
  backend (PATCH /users/me/fcm-token), show local notification on
  foreground messages, refresh token on rotation
- app_view.dart: call initializePushNotifications() on authenticated state

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-18 12:43:41 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 5e92d2b908 fix: replace Timestamp.toDate() with DateTime.tryParse in score list screens
score.createdAt is now String (ISO 8601) not Firebase Timestamp, so .toDate()
was a compile error. Use DateTime.tryParse() with fallback to DateTime.now().

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-18 12:28:07 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 90aab51a26 fix: remove Firebase repository exports from all 8 package barrel files
Deleted firebase_*_repository.dart files were still re-exported, causing
compile errors. Barrel files now only export the API implementations.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-18 12:24:48 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 7fb0615169 fix: align Flutter API repositories with backend routes (Fase 3 prep)
- api_service_repository: use correct endpoints (/services/me, /services/professional,
  /professional/requests, /professional/history, /professional/calendar)
  instead of broken /services?userId= query params
- api_service_repository: fix status string↔enum, createService DTO,
  paginated {data,meta} response, stub setProfessionalScored/setUserScored,
  extract professionalId from nested professionals.user_id
- api_score_repository: fix /comments/user/:id and /comments/professional/:id
- api_professional_repository + api_user_repository: handle paginated response

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-17 18:29:47 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 af91e0ba04 chore: remove Firebase dependencies and legacy code (Fase 4)
- Delete all firebase_*_repository.dart files (replaced by api_* equivalents)
- Remove cloud_firestore, firebase_auth, firebase_storage, firebase_core from all package pubspecs
- Remove cloud_firestore from main pubspec.yaml
- Delete firebase_options.dart (no longer referenced)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-17 18:11:31 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 733384091c feat: migrate prosappco from Firebase to NestJS REST API (Fase 2)
- Replace all Firebase* repositories with Api* repositories using HTTP + SharedPreferences JWT
- Remove Firebase.initializeApp() and firebase_messaging background handler from main.dart
- Update DI (app_di.dart) to inject Api* repositories instead of Firebase* ones
- Replace all Timestamp/cloud_firestore usage with ISO 8601 String dates
- Stub PhoneVerificationService (Firebase phone OTP → backend OTP when implemented)
- Add ApiService singleton with JWT management in lib/services/
- Legacy firebase_*_repository.dart files preserved for Fase 4 cleanup

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-17 16:53:11 -05:00
Lizandro Guarnizo d575ca9244 upload 2024-10-14 14:16:16 -05:00
Lizandro Guarnizo 72ea541658 Create upload_keystore.jks 2024-10-14 14:10:54 -05:00
lizandrogd dcd697e885 update 2024-05-28 17:19:13 -05:00
Lizandro Guarnizo ac53cc7cb5 Actualizacion de plugin, 2024-05-28 16:09:37 -05:00
Lizandro Guarnizo 8899a3b79f Update pubspec.yaml 2024-05-27 15:46:02 -05:00
Lizandro Guarnizo b419e24b90 labelname en android 2024-05-21 21:06:37 -05:00
Lizandro Guarnizo e27955d671 up 2024-05-21 10:26:19 -05:00
lizandrogd 1c20d0c0cd update 2024-01-16 21:48:38 -05:00
lizandrogd 35657f89ac update 2024-01-16 21:48:32 -05:00
lizandrogd aaf82b4072 Merge branch 'main' of https://github.com/lizandrogd/prosappco 2023-12-03 12:42:05 -05:00
lizandrogd a99c2c242a update 2023-12-03 12:41:51 -05:00
lizandrogd 9762ba6998 up 2023-11-17 20:16:29 -05:00
lizandrogd a0193bb43f update 2023-11-16 20:04:35 -05:00
lizandrogd 5af3b24275 Merge branch 'main' of https://github.com/lizandrogd/prosappco 2023-11-08 17:28:11 -05:00
lizandrogd 5fc8e00f77 update 2023-11-08 17:28:09 -05:00
lizandrogd 0fce441291 up 2023-11-01 22:45:05 -05:00
lizandrogd 7e4ed51704 update 2023-11-01 21:38:05 -05:00
lizandrogd b1868fe204 update 2023-10-25 09:44:26 -05:00
lizandrogd 5e5301412a update funcional 2023-10-23 18:31:01 -05:00
lizandrogd 9a08f10313 update 2023-10-12 13:56:50 -05:00
lizandrogd 6520495bc7 update 2023-10-12 13:42:43 -05:00
lizandrogd cfa52bbbe8 update ios 2023-10-12 13:22:03 -05:00
lizandrogd 86a3ead552 Merge branch 'main' of https://github.com/DuarteJFelipe/prosappco 2023-09-15 15:52:59 -05:00
lizandrogd 0d1a06bcf9 update 2023-09-01 16:06:36 -05:00
lizandrogd 0467c613ad update 2023-08-31 12:26:55 -05:00
lizandrogd 8c616b2bd0 Merge branch 'main' of https://github.com/DuarteJFelipe/prosappco 2023-08-31 12:18:14 -05:00
lizandrogd 455f16294e update 2023-08-31 12:17:55 -05:00
lizandrogd 9c885daebc update 2023-08-25 08:56:34 -05:00
lizandrogd 1270f3a6b5 uodate 2023-08-22 23:51:31 -05:00
lizandrogd a22d7efc27 update 2023-08-22 17:21:11 -05:00
lizandrogd bb1a291bd9 update 2023-08-22 17:17:36 -05:00
lizandrogd e10469b4d3 Revert "Revert "notificacion desde cita""
This reverts commit 1e09cb470ebdcdb5b0f0e819a9c8484f73031e1c.
2023-08-22 16:12:55 -05:00
lizandrogd 1d36026cb7 Revert "notificacion chat"
This reverts commit 96edb73a88.
2023-08-22 16:00:57 -05:00
lizandrogd e29af3493f Revert "Revert "update""
This reverts commit 1361f0bbf7.
2023-08-22 16:00:53 -05:00
lizandrogd 459f590638 Revert "Revert "Revert "update"""
This reverts commit 0a84306afa.
2023-08-22 16:00:47 -05:00
lizandrogd 091c67d4cb update 2023-08-22 08:25:31 -05:00
lizandrogd 2114913137 update 2023-08-22 00:02:21 -05:00
lizandrogd b8905e936a update 2023-08-21 23:18:13 -05:00
lizandrogd 74e857bab3 jj 2023-08-21 22:25:51 -05:00
lizandrogd ede125d181 Revert "update"
This reverts commit d44da638b5.
2023-08-21 22:11:41 -05:00
lizandrogd d44da638b5 update 2023-08-21 21:48:47 -05:00
lizandrogd b6b7edcec9 update 2023-08-20 15:00:52 -05:00
lizandrogd ec47617dfd update 2023-08-17 20:37:24 -05:00
lizandrogd 809873894c update 2023-07-31 09:59:49 -05:00
lizandrogd 61ebde2ebb update 2023-07-10 09:46:18 -05:00
lizandrogd 05fa9438a1 update notificacion web 2023-06-19 01:24:14 -05:00
lizandrogd 6cdc6ce5d7 update 2023-06-15 10:26:02 -05:00
lizandrogd 8a3c2d9453 actualizacion 2023-06-05 07:59:24 -05:00
lizandrogd e61512111a update 2023-05-15 17:27:15 -05:00
lizandrogd ebb6a97f2b Update login.dart 2023-03-27 15:26:50 -05:00