Hacktoberfest 2026: los issues que los mantenedores marcaron para octubre, abiertos y aptos para principiantes. Explorar issues de Hacktoberfest

Post-MVP rails sweep: viewer-zone formatting (34 files) and typed refusals (7 actions, 30 routes) in one bucket

Abierto
#1,663 0 comentarios 0 reacciones 0 asignados Ver en GitHub

Los mantenedores suelen responder en 1 día

Nadie ha tomado este issue todavía.

Evaluación

Dificultad
5/5
Tiempo estimado
Más de una semana
Aptitud para principiantes
42/100
Tipo de issue
Refactorización
Claridad
Bien especificado
Estado de actividad
Activo
Stack tecnológico
next.js, react, typescript

Línea de trabajo

Empieza por lib/time/viewer-zone.ts, lib/errors/refusal.ts y los rails existentes en tests/time/viewer-zone.test.ts y tests/errors/refusal-rails.test.ts. Audita los archivos de dashboard/components y las actions/routes indicados, verificando cada candidato antes de aplicar los patrones establecidos. Ejecuta ambas pin tests y las comprobaciones grep especificadas; se considera terminado cuando los dos barridos cumplen todas las condiciones indicadas sin añadir tests por archivo.

Escrito por el modelo de indexación a partir del texto del issue.

Descripción

enhancement

Why one issue

Two rails landed on 2026-09-15 and each was applied only to the sites that were visibly failing, on purpose (the Stream MVP is the priority): the typed Refusal (#1655, lib/errors/refusal.ts, docs/errors/01-refusals.md) and the viewer-zone formatting rail (#1657, lib/time/viewer-zone.ts, docs/booking/06-booking-lifecycle.md "Times are rendered in the viewer's zone"). This issue is the single bucket for finishing both sweeps after the MVP, so neither turns into a trickle of one-file PRs. Both are mechanical against an existing rail; both are Sonnet-tier work; both should ship as ONE PR each (or one combined), not per file.

Sweep A — bare date formatting on absolute instants (hydration + wrong-zone risk)

Every file below formats a Date with date-fns format(), toLocaleDateString, or a local-zone getter. On the server that is UTC and in the browser it is the user's zone, so any of them that server-renders can throw React #418 and re-render, and any of them shows the wrong wall-clock time to a user whose zone is not the runtime's. Replace with formatInViewerZone / formatForViewer and thread the zone from getViewerZone() (RSC) or useViewerZone() (client-only), exactly as AppointmentRow/NextUpHero do on #1657. The relative labels (getProximityLabel, CountdownBadge, DayGroupHeader's isToday, AppointmentList.dayKey) are the same bug at day boundaries and belong here too.

  • app/dashboard/consultant/[consultantId]/(features)/analytics/AnalyticsPageClient.tsx
  • app/dashboard/consultant/[consultantId]/(features)/documents/DocumentsTab.tsx
  • app/dashboard/consultant/[consultantId]/(features)/earnings/EarningsSummaryPanel.tsx
  • app/dashboard/consultant/[consultantId]/(features)/recordings/components/RecordingCard.tsx
  • app/dashboard/consultee/[consulteeId]/(features)/home/HomeTab.tsx
  • app/dashboard/organization/[orgId]/appointments/AppointmentsPageClient.tsx
  • app/dashboard/organization/[orgId]/documents/DocumentsClient.tsx
  • app/dashboard/organization/[orgId]/recordings/RecordingsClient.tsx
  • app/dashboard/organization/[orgId]/reimbursements/page.tsx
  • app/dashboard/staff/[staffId]/(features)/home/HomePageClient.tsx
  • app/explore/experts/[consultantId]/components/SubscriptionPricingToggle.tsx
  • app/form/onboarding/components/experience/CertificationsSection.tsx
  • app/form/onboarding/components/experience/WorkExperienceSection.tsx
  • AppointmentList.tsx
  • AppointmentRow.tsx
  • components/admin/WaitlistManagement.tsx
  • components/appointments/AppointmentCalendar.tsx
  • components/appointments/AppointmentRow.tsx
  • components/appointments/AppointmentSheet.tsx
  • components/appointments/DayGroupHeader.tsx
  • components/appointments/detail/AppointmentDetailClient.tsx
  • components/appointments/detail/AppointmentDocumentsList.tsx
  • components/appointments/detail/RescheduleProposalCard.tsx
  • components/appointments/HeldSlotBadge.tsx
  • components/appointments/NextUpHero.tsx
  • components/appointments/SessionTimeline.tsx
  • components/chat/CustomMessage.tsx
  • components/dashboard/shared/DocumentsPage.tsx
  • components/scheduling/SessionReleasePicker.tsx
  • components/scheduling/UnifiedCalendar.tsx
  • DayGroupHeader.tsx
  • EarningsSummaryPanel.tsx
  • NextUpHero.tsx
  • page.tsx

Sweep B — refusals still thrown as plain Errors

Server actions that throw new Error("Unauthorized …") are captured by Next's onRequestError; routes that answer a hand-built 4xx while also calling Sentry.captureException produce an error-level issue for a modelled "no". Convert each to a Refusal answered through apiError (routes) or returned as an ActionResult (actions), with a userMessage for the toast and a devMessage for the log — the shape #1655 established. Verify each candidate against the code before converting; some 4xx sites are genuine faults and should stay captured.

Server actions (count of refusal-shaped throws):

  • actions/stream/chat/event-channel.action.ts
  • actions/stream/chat/stream.action.ts
  • actions/stream/chat/user.action.ts
  • actions/stream/chat/member.action.ts

Route handlers that both capture to Sentry and answer a 4xx (candidates, not verdicts):

  • app/api/admin/compliance/tds-return/route.ts
  • app/api/admin/disputes/[disputeId]/route.ts
  • app/api/admin/erasure-requests/[id]/process/route.ts
  • app/api/admin/maintenance/route.ts
  • app/api/admin/payments/[paymentId]/route.ts
  • app/api/admin/payouts/[id]/route.ts
  • app/api/admin/reconcile-ledgers/route.ts
  • app/api/admin/tds/route.ts
  • app/api/admin/users/[userId]/route.ts
  • app/api/admin/verification/[verificationId]/route.ts
  • app/api/admin/waitlist/broadcast/route.ts
  • app/api/announcements/[id]/route.ts
  • app/api/announcements/route.ts
  • app/api/appointments/[appointmentId]/cancel/preview/route.ts
  • app/api/appointments/[appointmentId]/cancel/route.ts
  • app/api/appointments/[appointmentId]/documents/[documentId]/download/route.ts
  • app/api/appointments/[appointmentId]/documents/[documentId]/route.ts
  • app/api/appointments/[appointmentId]/documents/consultant/route.ts
  • app/api/appointments/[appointmentId]/documents/route.ts
  • app/api/appointments/[appointmentId]/reschedule/route.ts
  • app/api/appointments/[appointmentId]/support/route.ts
  • app/api/bookings/classes/[classId]/route.ts
  • app/api/bookings/classes/[classId]/validate/route.ts
  • app/api/bookings/classes/crud-with-plan/[classId]/route.ts
  • app/api/bookings/classes/crud-with-plan/route.ts
  • app/api/bookings/consultations/[consultationId]/route.ts
  • app/api/bookings/consultations/[consultationId]/validate/route.ts
  • app/api/bookings/consultations/route.ts
  • app/api/bookings/subscriptions/[subscriptionId]/route.ts
  • app/api/bookings/subscriptions/[subscriptionId]/validate/route.ts

Done when

  • No format( / toLocale* on an absolute instant outside lib/time/; grep -rln 'from "date-fns"' --include=*.tsx components app | xargs grep -l "format(" returns only files that format durations or already pass a zone.
  • No server action throws a refusal-shaped Error; no route answers a 4xx for a modelled refusal while also capturing it.
  • One pin per rail already exists (__tests__/time/viewer-zone.test.ts, __tests__/errors/refusal-rails.test.ts); do not add per-file tests.

Part of the post-MVP hardening; see #1645 (the sweeps-treat-permanent-as-transient lesson), #1655, #1657.

Lenguaje dominante
TypeScript
Estrellas
4
Forks
4
Merge medio
9 h 48 min
PR fusionados (30 d)
230

Preparar el entorno

Aún no hemos revisado los archivos de configuración de este proyecto. Empieza por su README y consulta nuestra guía para la primera contribución para los pasos generales.

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Más de Practitionist/familiarise_web

Todos los issues de Practitionist/familiarise_web

Issues similares

Más issues de TypeScript

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.