Fixes
CI / ci (push) Canceled after 0s

fixed super admin showing in client list

added a reconnect button to google calendar syncying

fixed ui issue with whatsapp undo link
This commit is contained in:
Stefan Lazic committed 2026-10-17 09:35:52 +01:00
1 parent 2ed9c5ecca
commit 05ea83e059
21 files changed
+1180 -118

No files matched your search

+33 -7
View File
@@ -96,7 +96,7 @@ async function syncOneConnection(
};
provider: CalendarProvider;
},
): Promise<void> {
): Promise<"ok" | "revoked"> {
const appointment = await prisma.appointment.findUnique({
where: { id: params.appointmentId },
include: {
@@ -105,7 +105,7 @@ async function syncOneConnection(
business: { select: { name: true, locations: { where: { isPrimary: true }, take: 1 } } },
},
});
if (!appointment) return;
if (!appointment) return "ok";
const provider = params.provider;
const existing = await prisma.appointmentCalendarEvent.findUnique({
@@ -113,7 +113,7 @@ async function syncOneConnection(
});
try {
if (appointment.status === AppointmentStatus.PENDING) return;
if (appointment.status === AppointmentStatus.PENDING) return "ok";
const accessToken = await getValidAccessToken(prisma, params.connection, provider);
@@ -125,7 +125,7 @@ async function syncOneConnection(
data: { status: CalendarSyncStatus.CANCELLED, lastSyncedAt: new Date(), lastSyncError: null },
});
}
return;
return "ok";
}
const event = buildEventContent(appointment);
@@ -163,14 +163,37 @@ async function syncOneConnection(
}
await prisma.staffCalendarConnection.update({ where: { id: params.connection.id }, data: { lastSyncAt: new Date(), lastSyncError: null } });
return "ok";
} catch (error) {
const message = error instanceof CalendarProviderError ? error.message : "Calendar sync failed unexpectedly.";
await prisma.staffCalendarConnection.update({ where: { id: params.connection.id }, data: { lastSyncError: message } }).catch(() => {});
// The user only ever sees `message`; the server log gets what's needed to
// diagnose it (Google's status and reason — never tokens or the payload).
console.error(
`[CalendarSync] appointment ${params.appointmentId} failed:`,
error instanceof CalendarProviderError ? `${error.code}${error.detail ? ` (${error.detail})` : ""}` : error,
);
const revoked = error instanceof CalendarProviderError && error.code === "TOKEN_REVOKED";
await prisma.staffCalendarConnection
.update({
where: { id: params.connection.id },
// A dead refresh token can never work again, so stop pretending to be
// connected: mark it revoked (the settings page then offers
// "Reconnect", and every later sync short-circuits instead of
// hammering Google with a token it has already refused) and keep the
// reason so the page can explain why.
data: revoked
? { lastSyncError: message, revokedAt: new Date(), encryptedAccessToken: null, tokenExpiresAt: null }
: { lastSyncError: message },
})
.catch(() => {});
if (existing) {
await prisma.appointmentCalendarEvent
.update({ where: { id: existing.id }, data: { status: CalendarSyncStatus.FAILED, lastSyncError: message } })
.catch(() => {});
}
return revoked ? "revoked" : "ok";
}
}
@@ -250,8 +273,11 @@ export async function runInitialSync(
select: { id: true },
});
let synced = 0;
for (const appointment of appointments) {
await syncOneConnection(prisma, { appointmentId: appointment.id, connection, provider });
const outcome = await syncOneConnection(prisma, { appointmentId: appointment.id, connection, provider });
if (outcome === "revoked") break; // every remaining one would fail the same way
synced++;
}
return { synced: appointments.length };
return { synced };
}