Skip to content

Commit

Permalink
Merge branch 'feat--add-qr-code' of https://github.com/corona-school/…
Browse files Browse the repository at this point in the history
…user-app into feat--add-qr-code
  • Loading branch information
MartinEichinger committed Oct 16, 2024
2 parents 3241428 + fecdde1 commit e53b301
Show file tree
Hide file tree
Showing 25 changed files with 213 additions and 189 deletions.
6 changes: 6 additions & 0 deletions src/Utility.ts
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,11 @@ export const sortByDate = <Subcourse extends { firstLecture?: { start: any } | n
});
};

export const renderTextWithEmailLinks = (text: string) => {
const emailRegex = /([a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,})/g;
return text.replace(emailRegex, '<a class="underline" href="mailto:$1">$1</a>');
};

const Utility = {
createToken,
toTimerString,
Expand All @@ -165,5 +170,6 @@ const Utility = {
handleDateString,
getTrafficStatus,
sortByDate,
renderTextWithEmailLinks,
};
export default Utility;
5 changes: 0 additions & 5 deletions src/assets/icons/lernfair/icon_achtung.svg

This file was deleted.

37 changes: 37 additions & 0 deletions src/components/Logout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import useApollo from '../hooks/useApollo';
import { useLocation, useNavigate } from 'react-router-dom';
import { useCallback, useContext } from 'react';
import { WebPushContext } from '@/context/WebPushProvider';
import { WEBPUSH_ACTIVE } from '@/config';
import { logError } from '@/log';
import CenterLoadingSpinner from '@/components/CenterLoadingSpinner';

export default function Logout() {
const navigate = useNavigate();
const location = useLocation();
const locState = location.state as { deactivated?: boolean };

const useLogout = () => {
const { logout } = useApollo();
const { unsubscribe } = useContext(WebPushContext);
return useCallback(async () => {
if (WEBPUSH_ACTIVE) {
try {
await unsubscribe();
} catch (error) {
logError('WebPush', 'Failed to unsubscribe', error);
}
}
try {
await logout();
} catch (error) {
logError('Authentication', 'Failed to logout', error);
}
}, []);
};

const logout = useLogout();
logout().then(() => navigate('/welcome', { state: locState }));

return <CenterLoadingSpinner />;
}
70 changes: 61 additions & 9 deletions src/components/appointment/AppointmentDetail.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import AppointmentMetaDetails from './AppointmentMetaDetails';
import Header from './Header';
import Avatars from './Avatars';
import Description from './Description';
import Buttons from './Buttons';
import { DateTime } from 'luxon';
import { useMutation } from '@apollo/client';
import useApollo from '../../hooks/useApollo';
Expand All @@ -15,6 +14,9 @@ import RejectAppointmentModal, { RejectType } from '../../modals/RejectAppointme
import { gql } from '../../gql';
import { Lecture_Appointmenttype_Enum } from '../../gql/graphql';
import { PUPIL_APPOINTMENT } from '../../pages/Appointment';
import { Typography } from '../Typography';
import { IconInfoCircle, IconClockEdit, IconTrash, IconPencil } from '@tabler/icons-react';
import { Button } from '../Button';

type AppointmentDetailProps = {
appointment: Appointment;
Expand Down Expand Up @@ -138,6 +140,10 @@ const AppointmentDetail: React.FC<AppointmentDetailProps> = ({ appointment }) =>
: `http://localhost:3000/login-token?secret_token=${token}`
);
};
const wasRejected = !!appointment.participants?.every((e) => appointment.declinedBy?.includes(e.userID!));
const byMatch = !appointment.declinedBy?.includes(user?.userID!);
const wasRejectedByMe = appointment.declinedBy?.includes(user?.userID!);
const wasRejectedByMatch = appointment.appointmentType === 'match' && wasRejected && byMatch;

return (
<>
Expand Down Expand Up @@ -169,15 +175,61 @@ const AppointmentDetail: React.FC<AppointmentDetailProps> = ({ appointment }) =>
zoomMeetingUrl={appointment.zoomMeetingUrl}
qrCodeLink={loginHref}
/>
{wasRejectedByMatch && (
<>
<div className="flex gap-x-1 items-center mt-4">
<IconInfoCircle className="text-red-600" size={18} />
<Typography className="text-red-600">{t('appointment.detail.cancelledBy', { name: appointment.displayName })}</Typography>
</div>
<Typography>{t('appointment.detail.rescheduleDescription', { name: appointment.displayName })}</Typography>
</>
)}
<Description description={appointment.description} />

<Buttons
onPress={user?.pupil ? () => setShowDeclineModal(true) : () => setShowDeleteModal(true)}
onEditPress={() => navigate(`/edit-appointment/${appointment.id}`)}
canceled={(appointment.declinedBy?.includes(user?.userID ?? '') ?? false) || canceled}
isOver={isPastAppointment}
isLast={isLastAppointment}
/>
<div className="flex flex-col md:flex-row gap-3">
{user?.student && (
<>
<Button
disabled={isPastAppointment}
reasonDisabled={t('appointment.detail.reasonDisabled.editBtn.isOver')}
variant={wasRejectedByMatch ? 'default' : 'outline'}
onClick={() => navigate(`/edit-appointment/${appointment.id}`)}
className="w-full lg:w-[300px]"
leftIcon={wasRejectedByMatch ? <IconClockEdit /> : <IconPencil />}
>
{wasRejectedByMatch ? t('appointment.detail.rescheduleButton') : t('appointment.detail.editButton')}
</Button>
<Button
disabled={isPastAppointment || isLastAppointment}
reasonDisabled={
isPastAppointment
? t('appointment.detail.reasonDisabled.deleteBtn.isOver')
: t('appointment.detail.reasonDisabled.deleteBtn.isLast')
}
onClick={() => setShowDeleteModal(true)}
variant="destructive"
className="w-full lg:w-[300px]"
leftIcon={<IconTrash />}
>
{t('appointment.detail.deleteButton')}
</Button>
</>
)}
{user?.pupil && (
<Button
disabled={(wasRejectedByMe ?? false) || canceled || isPastAppointment}
reasonDisabled={
isPastAppointment
? t('appointment.detail.reasonDisabled.cancelBtn.isOver')
: t('appointment.detail.reasonDisabled.cancelBtn.isCancelled')
}
onClick={() => setShowDeclineModal(true)}
variant="destructive"
className="w-full lg:w-[300px]"
>
{t('appointment.detail.cancelButton')}
</Button>
)}
</div>
</Box>
</>
);
Expand Down
71 changes: 0 additions & 71 deletions src/components/appointment/Buttons.tsx

This file was deleted.

27 changes: 0 additions & 27 deletions src/hooks/useLogout.ts

This file was deleted.

8 changes: 6 additions & 2 deletions src/lang/ar.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@
},
"appointmentTile": {
"lecture": "الدرس #{{position}}",
"title": ": {{appointmentTitle}}"
"title": ": {{appointmentTitle}}",
"cancelledBy": "تم إلغاؤه بواسطة {{name}}"
},
"create": {
"videoSelectOptions": {
Expand Down Expand Up @@ -109,7 +110,10 @@
"bp2": "الدردشة وإرسال الملفات مباشرةً من هاتفك الذكي",
"bp3": "تلقي إشعارات على الجهاز",
"footer": "ما عليك سوى مسح رمز الاستجابة السريعة ضوئياً باستخدام هاتفك الذكي"
}
},
"cancelledBy": "موعد {{name}} ألغيت هذه",
"rescheduleButton": "موعد المناوبة",
"rescheduleDescription": "موعد إذا قمت بتحريك، سيتم تحميل {{name}}} مرة أخرى."
},
"zoomModal": {
"useZoomApp": {
Expand Down
8 changes: 6 additions & 2 deletions src/lang/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,8 @@
},
"appointmentTile": {
"lecture": "Lektion #{{position}}",
"title": ": {{appointmentTitle}}"
"title": ": {{appointmentTitle}}",
"cancelledBy": "Abgesagt von {{name}}"
},
"create": {
"assignmentHeader": "Für welches Lernangebot soll dieser Termin erstellt werden?",
Expand Down Expand Up @@ -112,6 +113,7 @@
"deleteButton": "Termin löschen",
"cancelButton": "Termin absagen",
"editButton": "Termin bearbeiten",
"rescheduleButton": "Termin verschieben",
"canceledToast": "Termin wurde abgesagt",
"zoomTooltipStudent": "Wenn du diesen Link aufrufst, trittst du dem Meeting als Teilnehmer:in bei. Um als Host dem Meeting beizutrteten nutze den Button \"Jetzt Videochat beitreten\".",
"zoomTooltipPupil": "Teile diesen Link niemals mit anderen Personen. Nur so können wir die Sicherheit der Plattform gewährleisten.",
Expand All @@ -135,7 +137,9 @@
"bp2": "Direkt vom Smartphone chatten und Dateien senden",
"bp3": "Benachrichtigungen auf das Gerät erhalten",
"footer": "Einfach QR Code mit Smartphone scannen"
}
},
"cancelledBy": "{{name}} hat diesen Termin abgesagt",
"rescheduleDescription": "Wenn du den Termin verschiebst, wird {{name}} wieder eingeladen."
},
"zoomModal": {
"header": "Hinweise zum Videochat",
Expand Down
8 changes: 6 additions & 2 deletions src/lang/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@
},
"appointmentTile": {
"lecture": "Lesson #{{position}}",
"title": ": {{appointmentTitle}}"
"title": ": {{appointmentTitle}}",
"cancelledBy": "Canceled by {{name}}"
},
"create": {
"videoSelectOptions": {
Expand Down Expand Up @@ -109,7 +110,10 @@
"bp2": "Chat and send files directly from your smartphone",
"bp3": "Receive notifications on the device",
"footer": "Simply scan the QR code with your smartphone"
}
},
"cancelledBy": "{{name}} has canceled this lecture ",
"rescheduleButton": "Reschedule appointment",
"rescheduleDescription": "If you reschedule the lecture, {{name}} will be invited again."
},
"zoomModal": {
"useZoomApp": {
Expand Down
8 changes: 6 additions & 2 deletions src/lang/ru.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@
},
"appointmentTile": {
"lecture": "Урок #{{position}}",
"title": ": {{appointmentTitle}}"
"title": ": {{appointmentTitle}}",
"cancelledBy": "Отменено {{name}}"
},
"create": {
"videoSelectOptions": {
Expand Down Expand Up @@ -109,7 +110,10 @@
"bp2": "Общайтесь и отправляйте файлы прямо со смартфона",
"bp3": "Получайте уведомления на устройство",
"footer": "Просто отсканируйте QR-код с помощью своего смартфона"
}
},
"cancelledBy": "{{name}} отменил эту встречу",
"rescheduleButton": "Отложить встречу",
"rescheduleDescription": "Если вы отложите встречу, {{name}} будет приглашен снова."
},
"zoomModal": {
"useZoomApp": {
Expand Down
8 changes: 6 additions & 2 deletions src/lang/tr.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@
},
"appointmentTile": {
"lecture": "Ders #{{position}}",
"title": ": {{appointmentTitle}}"
"title": ": {{appointmentTitle}}",
"cancelledBy": "{{name}} tarafından iptal edildi"
},
"create": {
"videoSelectOptions": {
Expand Down Expand Up @@ -109,7 +110,10 @@
"bp2": "Doğrudan akıllı telefonunuzdan sohbet edin ve dosya gönderin",
"bp3": "Cihaz üzerinden bildirim alma",
"footer": "QR kodunu akıllı telefonunuzla taramanız yeterli"
}
},
"cancelledBy": "{{name}} bu randevuyu iptal etti",
"rescheduleButton": "Randevuyu ertele",
"rescheduleDescription": "Randevuyu ertelerseniz, {{name}} tekrar davet edilecektir."
},
"zoomModal": {
"useZoomApp": {
Expand Down
Loading

0 comments on commit e53b301

Please sign in to comment.