Merge pull request 'Refactor appointment components to replace Jitsi meeting URLs with moderator and participant join URLs. Update logic for joining meetings and copying room IDs based on user roles, enhancing clarity in the UI. Modify appointment model to support new joi…' (#43) from feat/booking-panel into master
Reviewed-on: http://35.207.46.142/ATTUNE-HEART-THERAPY/website/pulls/43
This commit is contained in:
commit
36014ca954
@ -494,7 +494,7 @@ export default function AppointmentDetailPage() {
|
||||
)}
|
||||
|
||||
{/* Meeting Information */}
|
||||
{appointment.jitsi_meet_url && (
|
||||
{appointment.moderator_join_url && (
|
||||
<div className={`rounded-2xl border shadow-sm overflow-hidden ${isDark ? "bg-gradient-to-br from-blue-900/20 to-purple-900/20 border-blue-800/30" : "bg-gradient-to-br from-blue-50 to-purple-50 border-blue-200"}`}>
|
||||
<div className={`px-6 py-4 border-b ${isDark ? "border-blue-800/30" : "border-blue-200"}`}>
|
||||
<h2 className={`text-lg font-semibold flex items-center gap-2 ${isDark ? "text-white" : "text-gray-900"}`}>
|
||||
@ -513,10 +513,10 @@ export default function AppointmentDetailPage() {
|
||||
{appointment.jitsi_room_id}
|
||||
</p>
|
||||
<button
|
||||
onClick={() => appointment.can_join_meeting && copyToClipboard(appointment.jitsi_room_id!, "Room ID")}
|
||||
disabled={!appointment.can_join_meeting}
|
||||
className={`p-2 rounded-lg transition-colors ${appointment.can_join_meeting ? (isDark ? "hover:bg-gray-700" : "hover:bg-gray-100") : (isDark ? "opacity-50 cursor-not-allowed" : "opacity-50 cursor-not-allowed")}`}
|
||||
title={appointment.can_join_meeting ? "Copy room ID" : "Meeting not available"}
|
||||
onClick={() => appointment.can_join_as_moderator && copyToClipboard(appointment.jitsi_room_id!, "Room ID")}
|
||||
disabled={!appointment.can_join_as_moderator}
|
||||
className={`p-2 rounded-lg transition-colors ${appointment.can_join_as_moderator ? (isDark ? "hover:bg-gray-700" : "hover:bg-gray-100") : (isDark ? "opacity-50 cursor-not-allowed" : "opacity-50 cursor-not-allowed")}`}
|
||||
title={appointment.can_join_as_moderator ? "Copy room ID" : "Meeting not available"}
|
||||
>
|
||||
<Copy className={`w-4 h-4 ${isDark ? "text-gray-400" : "text-gray-500"}`} />
|
||||
</button>
|
||||
@ -525,21 +525,21 @@ export default function AppointmentDetailPage() {
|
||||
)}
|
||||
<div>
|
||||
<p className={`text-xs font-medium mb-2 uppercase tracking-wider ${isDark ? "text-gray-400" : "text-gray-500"}`}>
|
||||
Meeting Link
|
||||
Moderator Meeting Link
|
||||
</p>
|
||||
<div className="flex items-center gap-2">
|
||||
{appointment.can_join_meeting ? (
|
||||
{appointment.can_join_as_moderator ? (
|
||||
<>
|
||||
<a
|
||||
href={appointment.jitsi_meet_url}
|
||||
href={appointment.moderator_join_url}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className={`flex-1 text-sm px-3 py-2 rounded-lg truncate ${isDark ? "bg-gray-800 text-blue-400 hover:bg-gray-700" : "bg-white text-blue-600 hover:bg-gray-50 border border-gray-200"}`}
|
||||
>
|
||||
{appointment.jitsi_meet_url}
|
||||
{appointment.moderator_join_url}
|
||||
</a>
|
||||
<a
|
||||
href={appointment.jitsi_meet_url}
|
||||
href={appointment.moderator_join_url}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className={`px-4 py-2 rounded-lg font-medium transition-colors ${isDark ? "bg-blue-600 hover:bg-blue-700 text-white" : "bg-blue-600 hover:bg-blue-700 text-white"}`}
|
||||
@ -550,7 +550,7 @@ export default function AppointmentDetailPage() {
|
||||
) : (
|
||||
<>
|
||||
<div className={`flex-1 text-sm px-3 py-2 rounded-lg truncate ${isDark ? "bg-gray-800/50 text-gray-500 border border-gray-700" : "bg-gray-100 text-gray-400 border border-gray-300"}`}>
|
||||
{appointment.jitsi_meet_url}
|
||||
{appointment.moderator_join_url}
|
||||
</div>
|
||||
<button
|
||||
disabled
|
||||
@ -562,11 +562,11 @@ export default function AppointmentDetailPage() {
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
{appointment.can_join_meeting !== undefined && (
|
||||
<div className={`flex items-center gap-2 px-4 py-3 rounded-lg ${appointment.can_join_meeting ? (isDark ? "bg-green-500/20 border border-green-500/30" : "bg-green-50 border border-green-200") : (isDark ? "bg-gray-800 border border-gray-700" : "bg-gray-50 border border-gray-200")}`}>
|
||||
<div className={`h-2 w-2 rounded-full ${appointment.can_join_meeting ? (isDark ? "bg-green-400" : "bg-green-600") : (isDark ? "bg-gray-500" : "bg-gray-400")}`} />
|
||||
<p className={`text-sm font-medium ${appointment.can_join_meeting ? (isDark ? "text-green-300" : "text-green-700") : (isDark ? "text-gray-400" : "text-gray-500")}`}>
|
||||
{appointment.can_join_meeting ? "Meeting is active - You can join now" : "Meeting is not available yet"}
|
||||
{appointment.can_join_as_moderator !== undefined && (
|
||||
<div className={`flex items-center gap-2 px-4 py-3 rounded-lg ${appointment.can_join_as_moderator ? (isDark ? "bg-green-500/20 border border-green-500/30" : "bg-green-50 border border-green-200") : (isDark ? "bg-gray-800 border border-gray-700" : "bg-gray-50 border border-gray-200")}`}>
|
||||
<div className={`h-2 w-2 rounded-full ${appointment.can_join_as_moderator ? (isDark ? "bg-green-400" : "bg-green-600") : (isDark ? "bg-gray-500" : "bg-gray-400")}`} />
|
||||
<p className={`text-sm font-medium ${appointment.can_join_as_moderator ? (isDark ? "text-green-300" : "text-green-700") : (isDark ? "text-gray-400" : "text-gray-500")}`}>
|
||||
{appointment.can_join_as_moderator ? "Meeting is active - You can join as moderator" : "Meeting is not available yet"}
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
@ -636,18 +636,18 @@ export default function AppointmentDetailPage() {
|
||||
)}
|
||||
|
||||
{/* Join Meeting Button (if scheduled) */}
|
||||
{appointment.status === "scheduled" && appointment.jitsi_meet_url && (
|
||||
{appointment.status === "scheduled" && appointment.moderator_join_url && (
|
||||
<div className={`rounded-2xl border shadow-sm overflow-hidden ${isDark ? "bg-gradient-to-br from-blue-900/20 to-purple-900/20 border-blue-800/30" : "bg-gradient-to-br from-blue-50 to-purple-50 border-blue-200"}`}>
|
||||
<div className="p-6">
|
||||
{appointment.can_join_meeting ? (
|
||||
{appointment.can_join_as_moderator ? (
|
||||
<a
|
||||
href={appointment.jitsi_meet_url}
|
||||
href={appointment.moderator_join_url}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className={`flex items-center justify-center gap-2 w-full bg-blue-600 hover:bg-blue-700 text-white h-12 rounded-lg text-base font-medium transition-colors`}
|
||||
>
|
||||
<Video className="w-5 h-5" />
|
||||
Join Meeting
|
||||
Join Meeting as Moderator
|
||||
</a>
|
||||
) : (
|
||||
<button
|
||||
|
||||
@ -802,13 +802,13 @@ export default function Booking() {
|
||||
</button>
|
||||
</>
|
||||
)}
|
||||
{appointment.jitsi_meet_url && (
|
||||
{appointment.moderator_join_url && (
|
||||
<a
|
||||
href={appointment.jitsi_meet_url}
|
||||
href={appointment.moderator_join_url}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className={`p-1.5 sm:p-2 rounded-lg transition-colors ${isDark ? "text-gray-300 hover:text-white hover:bg-gray-700" : "text-gray-600 hover:text-gray-900 hover:bg-gray-100"}`}
|
||||
title="Join Meeting"
|
||||
title="Join Meeting as Moderator"
|
||||
>
|
||||
<Video className="w-4 h-4" />
|
||||
</a>
|
||||
|
||||
@ -433,7 +433,7 @@ export default function UserAppointmentDetailPage() {
|
||||
)}
|
||||
|
||||
{/* Meeting Information */}
|
||||
{appointment.jitsi_meet_url && (
|
||||
{appointment.participant_join_url && (
|
||||
<div className={`rounded-2xl border shadow-sm overflow-hidden ${isDark ? "bg-gradient-to-br from-blue-900/20 to-purple-900/20 border-blue-800/30" : "bg-gradient-to-br from-blue-50 to-purple-50 border-blue-200"}`}>
|
||||
<div className={`px-6 py-4 border-b ${isDark ? "border-blue-800/30" : "border-blue-200"}`}>
|
||||
<h2 className={`text-lg font-semibold flex items-center gap-2 ${isDark ? "text-white" : "text-gray-900"}`}>
|
||||
@ -452,10 +452,10 @@ export default function UserAppointmentDetailPage() {
|
||||
{appointment.jitsi_room_id}
|
||||
</p>
|
||||
<button
|
||||
onClick={() => appointment.can_join_meeting && copyToClipboard(appointment.jitsi_room_id!, "Room ID")}
|
||||
disabled={!appointment.can_join_meeting}
|
||||
className={`p-2 rounded-lg transition-colors ${appointment.can_join_meeting ? (isDark ? "hover:bg-gray-700" : "hover:bg-gray-100") : (isDark ? "opacity-50 cursor-not-allowed" : "opacity-50 cursor-not-allowed")}`}
|
||||
title={appointment.can_join_meeting ? "Copy room ID" : "Meeting not available"}
|
||||
onClick={() => appointment.can_join_as_participant && copyToClipboard(appointment.jitsi_room_id!, "Room ID")}
|
||||
disabled={!appointment.can_join_as_participant}
|
||||
className={`p-2 rounded-lg transition-colors ${appointment.can_join_as_participant ? (isDark ? "hover:bg-gray-700" : "hover:bg-gray-100") : (isDark ? "opacity-50 cursor-not-allowed" : "opacity-50 cursor-not-allowed")}`}
|
||||
title={appointment.can_join_as_participant ? "Copy room ID" : "Meeting not available"}
|
||||
>
|
||||
<Copy className={`w-4 h-4 ${isDark ? "text-gray-400" : "text-gray-500"}`} />
|
||||
</button>
|
||||
@ -467,18 +467,18 @@ export default function UserAppointmentDetailPage() {
|
||||
Meeting Link
|
||||
</p>
|
||||
<div className="flex items-center gap-2">
|
||||
{appointment.can_join_meeting ? (
|
||||
{appointment.can_join_as_participant ? (
|
||||
<>
|
||||
<a
|
||||
href={appointment.jitsi_meet_url}
|
||||
href={appointment.participant_join_url}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className={`flex-1 text-sm px-3 py-2 rounded-lg truncate ${isDark ? "bg-gray-800 text-blue-400 hover:bg-gray-700" : "bg-white text-blue-600 hover:bg-gray-50 border border-gray-200"}`}
|
||||
>
|
||||
{appointment.jitsi_meet_url}
|
||||
{appointment.participant_join_url}
|
||||
</a>
|
||||
<a
|
||||
href={appointment.jitsi_meet_url}
|
||||
href={appointment.participant_join_url}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className={`px-4 py-2 rounded-lg font-medium transition-colors ${isDark ? "bg-blue-600 hover:bg-blue-700 text-white" : "bg-blue-600 hover:bg-blue-700 text-white"}`}
|
||||
@ -489,7 +489,7 @@ export default function UserAppointmentDetailPage() {
|
||||
) : (
|
||||
<>
|
||||
<div className={`flex-1 text-sm px-3 py-2 rounded-lg truncate ${isDark ? "bg-gray-800/50 text-gray-500 border border-gray-700" : "bg-gray-100 text-gray-400 border border-gray-300"}`}>
|
||||
{appointment.jitsi_meet_url}
|
||||
{appointment.participant_join_url}
|
||||
</div>
|
||||
<button
|
||||
disabled
|
||||
@ -501,11 +501,11 @@ export default function UserAppointmentDetailPage() {
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
{appointment.can_join_meeting !== undefined && (
|
||||
<div className={`flex items-center gap-2 px-4 py-3 rounded-lg ${appointment.can_join_meeting ? (isDark ? "bg-green-500/20 border border-green-500/30" : "bg-green-50 border border-green-200") : (isDark ? "bg-gray-800 border border-gray-700" : "bg-gray-50 border border-gray-200")}`}>
|
||||
<div className={`h-2 w-2 rounded-full ${appointment.can_join_meeting ? (isDark ? "bg-green-400" : "bg-green-600") : (isDark ? "bg-gray-500" : "bg-gray-400")}`} />
|
||||
<p className={`text-sm font-medium ${appointment.can_join_meeting ? (isDark ? "text-green-300" : "text-green-700") : (isDark ? "text-gray-400" : "text-gray-500")}`}>
|
||||
{appointment.can_join_meeting ? "Meeting is active - You can join now" : "Meeting is not available yet"}
|
||||
{appointment.can_join_as_participant !== undefined && (
|
||||
<div className={`flex items-center gap-2 px-4 py-3 rounded-lg ${appointment.can_join_as_participant ? (isDark ? "bg-green-500/20 border border-green-500/30" : "bg-green-50 border border-green-200") : (isDark ? "bg-gray-800 border border-gray-700" : "bg-gray-50 border border-gray-200")}`}>
|
||||
<div className={`h-2 w-2 rounded-full ${appointment.can_join_as_participant ? (isDark ? "bg-green-400" : "bg-green-600") : (isDark ? "bg-gray-500" : "bg-gray-400")}`} />
|
||||
<p className={`text-sm font-medium ${appointment.can_join_as_participant ? (isDark ? "text-green-300" : "text-green-700") : (isDark ? "text-gray-400" : "text-gray-500")}`}>
|
||||
{appointment.can_join_as_participant ? "Meeting is active - You can join now" : "Meeting is not available yet"}
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
@ -552,12 +552,12 @@ export default function UserAppointmentDetailPage() {
|
||||
</div>
|
||||
|
||||
{/* Join Meeting Button */}
|
||||
{appointment.status === "scheduled" && appointment.jitsi_meet_url && (
|
||||
{appointment.status === "scheduled" && appointment.participant_join_url && (
|
||||
<div className={`rounded-2xl border shadow-sm overflow-hidden ${isDark ? "bg-gradient-to-br from-blue-900/20 to-purple-900/20 border-blue-800/30" : "bg-gradient-to-br from-blue-50 to-purple-50 border-blue-200"}`}>
|
||||
<div className="p-6">
|
||||
{appointment.can_join_meeting ? (
|
||||
{appointment.can_join_as_participant ? (
|
||||
<a
|
||||
href={appointment.jitsi_meet_url}
|
||||
href={appointment.participant_join_url}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className={`flex items-center justify-center gap-2 w-full bg-blue-600 hover:bg-blue-700 text-white h-12 rounded-lg text-base font-medium transition-colors`}
|
||||
|
||||
@ -458,13 +458,13 @@ export default function UserDashboard() {
|
||||
</td>
|
||||
<td className="px-3 sm:px-4 md:px-6 py-4 whitespace-nowrap text-right text-sm font-medium">
|
||||
<div className="flex items-center justify-end gap-1 sm:gap-2">
|
||||
{appointment.jitsi_meet_url && (
|
||||
{appointment.participant_join_url && (
|
||||
<a
|
||||
href={appointment.jitsi_meet_url}
|
||||
href={appointment.participant_join_url}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className={`p-1.5 sm:p-2 rounded-lg transition-colors ${
|
||||
appointment.can_join_meeting
|
||||
appointment.can_join_as_participant
|
||||
? isDark
|
||||
? "bg-blue-600 hover:bg-blue-700 text-white"
|
||||
: "bg-blue-600 hover:bg-blue-700 text-white"
|
||||
@ -472,10 +472,10 @@ export default function UserDashboard() {
|
||||
? "text-gray-400 hover:text-gray-300 hover:bg-gray-700"
|
||||
: "text-gray-500 hover:text-gray-700 hover:bg-gray-100"
|
||||
}`}
|
||||
title={appointment.can_join_meeting ? "Join Meeting" : "Meeting Not Available"}
|
||||
title={appointment.can_join_as_participant ? "Join Meeting" : "Meeting Not Available"}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
if (!appointment.can_join_meeting) {
|
||||
if (!appointment.can_join_as_participant) {
|
||||
e.preventDefault();
|
||||
}
|
||||
}}
|
||||
|
||||
@ -18,8 +18,17 @@ export interface Appointment {
|
||||
rejection_reason?: string;
|
||||
jitsi_meet_url?: string;
|
||||
jitsi_room_id?: string;
|
||||
jitsi_meeting_created?: boolean;
|
||||
meeting_started_at?: string;
|
||||
meeting_ended_at?: string;
|
||||
meeting_duration_actual?: number;
|
||||
meeting_info?: any;
|
||||
has_jitsi_meeting?: boolean | string;
|
||||
can_join_meeting?: boolean | string;
|
||||
can_join_as_moderator?: boolean | string;
|
||||
can_join_as_participant?: boolean | string;
|
||||
moderator_join_url?: string;
|
||||
participant_join_url?: string;
|
||||
meeting_status?: string;
|
||||
matching_availability?: MatchingAvailability | Array<{
|
||||
date: string;
|
||||
@ -39,6 +48,7 @@ export interface Appointment {
|
||||
|
||||
export interface SelectedSlot {
|
||||
day: number; // 0-6 (Monday-Sunday)
|
||||
date?: string; // YYYY-MM-DD format
|
||||
time_slot: "morning" | "afternoon" | "evening";
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user