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:
21 files changed
+1180
-118
No files matched your search
@@ -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 };
|
||||
}
|
||||
Reference in new issue
Block a user