diff --git a/frontend/src/i18n/en/translation.json b/frontend/src/i18n/en/translation.json
index ec30e553..c2085d0c 100644
--- a/frontend/src/i18n/en/translation.json
+++ b/frontend/src/i18n/en/translation.json
@@ -295,6 +295,8 @@
"searchMember": "Search member",
"inviteLink": "Invite link",
"inviteLinkInfo": "With this link, students can join your course",
+ "copyLink": "Copy invite link",
+ "copyLinkSuccess": "Link copied to clipboard",
"deleteCourse": "Delete course",
"deleteCourseDescription": "Are you sure you want to delete this course? All projects and submissions will be deleted as well. This action cannot be undone.",
"confirmDelete": "Confirm deletion",
diff --git a/frontend/src/i18n/nl/translation.json b/frontend/src/i18n/nl/translation.json
index 8bd0c05b..0a28e83a 100644
--- a/frontend/src/i18n/nl/translation.json
+++ b/frontend/src/i18n/nl/translation.json
@@ -299,6 +299,8 @@
"searchMember": "Zoek lid",
"inviteLink": "Uitnodigingslink",
"inviteLinkInfo": "Met deze link kunnen studenten zich inschrijven voor dit vak.",
+ "copyLink": "Kopieer uitnodiginslink",
+ "copyLinkSuccess": "Link gekopieerd",
"deleteCourse": "Vak verwijderen",
"deleteCourseDescription": "Bent u zeker dat u dit vak wilt verwijderen? Alle projecten en indieningen zullen ook verwijderd worden. Deze actie kan niet ongedaan gemaakt worden.",
"confirmDelete": "Bevestig verwijdering",
diff --git a/frontend/src/pages/course/components/informationTab/InformationTab.tsx b/frontend/src/pages/course/components/informationTab/InformationTab.tsx
index c4103355..0cbd4495 100644
--- a/frontend/src/pages/course/components/informationTab/InformationTab.tsx
+++ b/frontend/src/pages/course/components/informationTab/InformationTab.tsx
@@ -1,4 +1,5 @@
import { Card, Col, Row, Space, Tooltip, Typography, theme } from "antd"
+import { EditOutlined, CheckOutlined, CopyOutlined } from "@ant-design/icons"
import useCourse from "../../../../hooks/useCourse"
import MarkdownTextfield from "../../../../components/input/MarkdownTextfield"
import { InfoCircleOutlined } from "@ant-design/icons"
@@ -75,8 +76,12 @@ const InformationTab = () => {
{t("course.inviteLink")}:
- , ],
+ }}
editable={{
+ icon: ,
onStart: () => openInviteModal({course, modal, onChange: setCourse, title: t("course.invitePeopleToCourse")}),
}}
style={{color:token.colorLink, cursor:"default"}}
diff --git a/frontend/src/pages/course/components/tabExtraBtn/InviteModalContent.tsx b/frontend/src/pages/course/components/tabExtraBtn/InviteModalContent.tsx
index 4b92e977..ec4a050e 100644
--- a/frontend/src/pages/course/components/tabExtraBtn/InviteModalContent.tsx
+++ b/frontend/src/pages/course/components/tabExtraBtn/InviteModalContent.tsx
@@ -1,19 +1,21 @@
-import { Button, Input, Modal, Space, Switch, Tooltip, Typography } from "antd"
+import { Button, Input, Modal, Space, Switch, Tooltip, Typography, theme, message } from "antd"
import { FC, useMemo, useState } from "react"
import { generateLink } from "../informationTab/InformationTab"
import { CourseType } from "../../Course"
import { HookAPI } from "antd/es/modal/useModal"
-import { InfoCircleOutlined, RedoOutlined } from "@ant-design/icons"
+import { InfoCircleOutlined, RedoOutlined, CopyOutlined, CheckOutlined } from "@ant-design/icons"
import { useTranslation } from "react-i18next"
import useApi from "../../../../hooks/useApi"
import { ApiRoutes } from "../../../../@types/requests.d"
const InviteModalContent: FC<{ defaultCourse: CourseType; onChange: (course: CourseType) => void }> = ({ defaultCourse, onChange }) => {
const { t } = useTranslation()
+ const { token } = theme.useToken()
const [course, setCourse] = useState(defaultCourse)
const API = useApi()
const [loading, setLoading] = useState(false)
const url = useMemo(() => generateLink(course.courseId.toString(), course.joinKey), [course])
+ const [copied, setCopied] = useState(false)
const regenerateKey = async () => {
setLoading(true)
@@ -47,13 +49,21 @@ const InviteModalContent: FC<{ defaultCourse: CourseType; onChange: (course: Cou
>
-
-
+
+ {copied ? (
+
+ ) : (
+ {
+ navigator.clipboard.writeText(url);
+ setCopied(true);
+ setTimeout(() => setCopied(false), 3000); // Reset after 3 seconds
+ }} />
+ )}
+
}
/>
{course.joinKey && (