feat: format with prettier

This commit is contained in:
swve 2024-02-09 21:22:15 +01:00
parent 03fb09c3d6
commit a147ad6610
164 changed files with 11257 additions and 8154 deletions

View file

@ -1,112 +1,144 @@
import React, { useState } from "react";
import DynamicPageActivityImage from "public/activities_types/dynamic-page-activity.png";
import VideoPageActivityImage from "public//activities_types/video-page-activity.png";
import DocumentPdfPageActivityImage from "public//activities_types/documentpdf-page-activity.png";
import { styled } from '@stitches/react';
import DynamicCanvaModal from "./NewActivityModal/DynamicCanva";
import VideoModal from "./NewActivityModal/Video";
import Image from "next/image";
import DocumentPdfModal from "./NewActivityModal/DocumentPdf";
function NewActivityModal({ closeModal, submitActivity, submitFileActivity, submitExternalVideo, chapterId, course }: any) {
const [selectedView, setSelectedView] = useState("home");
import React, { useState } from 'react'
import DynamicPageActivityImage from 'public/activities_types/dynamic-page-activity.png'
import VideoPageActivityImage from 'public//activities_types/video-page-activity.png'
import DocumentPdfPageActivityImage from 'public//activities_types/documentpdf-page-activity.png'
import { styled } from '@stitches/react'
import DynamicCanvaModal from './NewActivityModal/DynamicCanva'
import VideoModal from './NewActivityModal/Video'
import Image from 'next/image'
import DocumentPdfModal from './NewActivityModal/DocumentPdf'
function NewActivityModal({
closeModal,
submitActivity,
submitFileActivity,
submitExternalVideo,
chapterId,
course,
}: any) {
const [selectedView, setSelectedView] = useState('home')
return (
<div>
{selectedView === "home" && (
{selectedView === 'home' && (
<ActivityChooserWrapper>
<ActivityOption onClick={() => { setSelectedView("dynamic") }}>
<ActivityOption
onClick={() => {
setSelectedView('dynamic')
}}
>
<ActivityTypeImage>
<Image alt="Dynamic Page" src={DynamicPageActivityImage}></Image>
</ActivityTypeImage>
<ActivityTypeTitle>Dynamic Page</ActivityTypeTitle>
</ActivityOption>
<ActivityOption onClick={() => { setSelectedView("video") }}>
<ActivityOption
onClick={() => {
setSelectedView('video')
}}
>
<ActivityTypeImage>
<Image alt="Video Page" src={VideoPageActivityImage}></Image>
</ActivityTypeImage>
<ActivityTypeTitle>Video Page</ActivityTypeTitle>
</ActivityOption>
<ActivityOption onClick={() => { setSelectedView("documentpdf") }}>
<ActivityOption
onClick={() => {
setSelectedView('documentpdf')
}}
>
<ActivityTypeImage>
<Image alt="Document PDF Page" src={DocumentPdfPageActivityImage}></Image>
<Image
alt="Document PDF Page"
src={DocumentPdfPageActivityImage}
></Image>
</ActivityTypeImage>
<ActivityTypeTitle>PDF Document Page</ActivityTypeTitle>
</ActivityOption>
</ActivityChooserWrapper>
)}
{selectedView === "dynamic" && (
<DynamicCanvaModal submitActivity={submitActivity} chapterId={chapterId} course={course} />
{selectedView === 'dynamic' && (
<DynamicCanvaModal
submitActivity={submitActivity}
chapterId={chapterId}
course={course}
/>
)}
{selectedView === "video" && (
<VideoModal submitFileActivity={submitFileActivity} submitExternalVideo={submitExternalVideo}
chapterId={chapterId} course={course} />
{selectedView === 'video' && (
<VideoModal
submitFileActivity={submitFileActivity}
submitExternalVideo={submitExternalVideo}
chapterId={chapterId}
course={course}
/>
)}
{selectedView === "documentpdf" && (
<DocumentPdfModal submitFileActivity={submitFileActivity} chapterId={chapterId} course={course} />
{selectedView === 'documentpdf' && (
<DocumentPdfModal
submitFileActivity={submitFileActivity}
chapterId={chapterId}
course={course}
/>
)}
</div>
);
)
}
const ActivityChooserWrapper = styled("div", {
display: "flex",
flexDirection: "row",
justifyContent: "start",
const ActivityChooserWrapper = styled('div', {
display: 'flex',
flexDirection: 'row',
justifyContent: 'start',
marginTop: 10,
});
})
const ActivityOption = styled("div", {
width: "180px",
textAlign: "center",
const ActivityOption = styled('div', {
width: '180px',
textAlign: 'center',
borderRadius: 10,
background: "#F6F6F6",
border: "4px solid #F5F5F5",
margin: "auto",
background: '#F6F6F6',
border: '4px solid #F5F5F5',
margin: 'auto',
// hover
"&:hover": {
cursor: "pointer",
background: "#ededed",
border: "4px solid #ededed",
// hover
'&:hover': {
cursor: 'pointer',
background: '#ededed',
border: '4px solid #ededed',
transition: "background 0.2s ease-in-out, border 0.2s ease-in-out",
transition: 'background 0.2s ease-in-out, border 0.2s ease-in-out',
},
});
})
const ActivityTypeImage = styled("div", {
const ActivityTypeImage = styled('div', {
height: 80,
borderRadius: 8,
margin: 2,
display: "flex",
flexDirection: "column",
alignItems: "center",
justifyContent: "end",
textAlign: "center",
background: "#ffffff",
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'end',
textAlign: 'center',
background: '#ffffff',
// hover
"&:hover": {
cursor: "pointer",
// hover
'&:hover': {
cursor: 'pointer',
},
});
})
const ActivityTypeTitle = styled("div", {
display: "flex",
const ActivityTypeTitle = styled('div', {
display: 'flex',
fontSize: 12,
height: "20px",
height: '20px',
fontWeight: 500,
color: "rgba(0, 0, 0, 0.38);",
color: 'rgba(0, 0, 0, 0.38);',
// center text vertically
alignItems: "center",
justifyContent: "center",
textAlign: "center",
alignItems: 'center',
justifyContent: 'center',
textAlign: 'center',
})
});
export default NewActivityModal;
export default NewActivityModal

View file

@ -1,40 +1,56 @@
import FormLayout, { ButtonBlack, Flex, FormField, FormLabel, FormMessage, Input } from "@components/StyledElements/Form/Form";
import React, { useState } from "react";
import * as Form from '@radix-ui/react-form';
import BarLoader from "react-spinners/BarLoader";
import FormLayout, {
ButtonBlack,
Flex,
FormField,
FormLabel,
FormMessage,
Input,
} from '@components/StyledElements/Form/Form'
import React, { useState } from 'react'
import * as Form from '@radix-ui/react-form'
import BarLoader from 'react-spinners/BarLoader'
function DocumentPdfModal({ submitFileActivity, chapterId, course }: any) {
const [documentpdf, setDocumentPdf] = React.useState(null) as any;
const [isSubmitting, setIsSubmitting] = useState(false);
const [name, setName] = React.useState("");
const [documentpdf, setDocumentPdf] = React.useState(null) as any
const [isSubmitting, setIsSubmitting] = useState(false)
const [name, setName] = React.useState('')
const handleDocumentPdfChange = (event: React.ChangeEvent<any>) => {
setDocumentPdf(event.target.files[0]);
};
setDocumentPdf(event.target.files[0])
}
const handleNameChange = (event: React.ChangeEvent<HTMLInputElement>) => {
setName(event.target.value);
};
setName(event.target.value)
}
const handleSubmit = async (e: any) => {
e.preventDefault();
setIsSubmitting(true);
let status = await submitFileActivity(documentpdf, "documentpdf", { name: name,
chapter_id: chapterId,
activity_type: "TYPE_DOCUMENT",
activity_sub_type:"SUBTYPE_DOCUMENT_PDF",
published_version:1,
version:1,
course_id: course.id, }, chapterId);
setIsSubmitting(false);
};
e.preventDefault()
setIsSubmitting(true)
let status = await submitFileActivity(
documentpdf,
'documentpdf',
{
name: name,
chapter_id: chapterId,
activity_type: 'TYPE_DOCUMENT',
activity_sub_type: 'SUBTYPE_DOCUMENT_PDF',
published_version: 1,
version: 1,
course_id: course.id,
},
chapterId
)
setIsSubmitting(false)
}
return (
<FormLayout onSubmit={handleSubmit}>
<FormLayout onSubmit={handleSubmit}>
<FormField name="documentpdf-activity-name">
<Flex css={{ alignItems: 'baseline', justifyContent: 'space-between' }}>
<FormLabel>PDF Document name</FormLabel>
<FormMessage match="valueMissing">Please provide a name for your PDF Document activity</FormMessage>
<FormMessage match="valueMissing">
Please provide a name for your PDF Document activity
</FormMessage>
</Flex>
<Form.Control asChild>
<Input onChange={handleNameChange} type="text" required />
@ -43,7 +59,9 @@ function DocumentPdfModal({ submitFileActivity, chapterId, course }: any) {
<FormField name="documentpdf-activity-file">
<Flex css={{ alignItems: 'baseline', justifyContent: 'space-between' }}>
<FormLabel>PDF Document file</FormLabel>
<FormMessage match="valueMissing">Please provide a PDF Document for your activity</FormMessage>
<FormMessage match="valueMissing">
Please provide a PDF Document for your activity
</FormMessage>
</Flex>
<Form.Control asChild>
<input type="file" onChange={handleDocumentPdfChange} required />
@ -52,13 +70,21 @@ function DocumentPdfModal({ submitFileActivity, chapterId, course }: any) {
<Flex css={{ marginTop: 25, justifyContent: 'flex-end' }}>
<Form.Submit asChild>
<ButtonBlack type="submit" css={{ marginTop: 10 }}>
{isSubmitting ? <BarLoader cssOverride={{borderRadius:60,}} width={60} color="#ffffff" /> : "Create activity"}
<ButtonBlack type="submit" css={{ marginTop: 10 }}>
{isSubmitting ? (
<BarLoader
cssOverride={{ borderRadius: 60 }}
width={60}
color="#ffffff"
/>
) : (
'Create activity'
)}
</ButtonBlack>
</Form.Submit>
</Flex>
</FormLayout>
);
)
}
export default DocumentPdfModal;
export default DocumentPdfModal

View file

@ -1,41 +1,51 @@
import FormLayout, { ButtonBlack, Flex, FormField, FormLabel, FormMessage, Input, Textarea } from "@components/StyledElements/Form/Form";
import React, { useState } from "react";
import * as Form from '@radix-ui/react-form';
import BarLoader from "react-spinners/BarLoader";
import FormLayout, {
ButtonBlack,
Flex,
FormField,
FormLabel,
FormMessage,
Input,
Textarea,
} from '@components/StyledElements/Form/Form'
import React, { useState } from 'react'
import * as Form from '@radix-ui/react-form'
import BarLoader from 'react-spinners/BarLoader'
function DynamicCanvaModal({ submitActivity, chapterId, course }: any) {
const [activityName, setActivityName] = useState("");
const [activityDescription, setActivityDescription] = useState("");
const [isSubmitting, setIsSubmitting] = useState(false);
const [activityName, setActivityName] = useState('')
const [activityDescription, setActivityDescription] = useState('')
const [isSubmitting, setIsSubmitting] = useState(false)
const handleActivityNameChange = (e: any) => {
setActivityName(e.target.value);
};
setActivityName(e.target.value)
}
const handleActivityDescriptionChange = (e: any) => {
setActivityDescription(e.target.value);
};
setActivityDescription(e.target.value)
}
const handleSubmit = async (e: any) => {
e.preventDefault();
setIsSubmitting(true);
e.preventDefault()
setIsSubmitting(true)
await submitActivity({
name: activityName,
chapter_id: chapterId,
activity_type: "TYPE_DYNAMIC",
activity_sub_type:"SUBTYPE_DYNAMIC_PAGE",
published_version:1,
version:1,
activity_type: 'TYPE_DYNAMIC',
activity_sub_type: 'SUBTYPE_DYNAMIC_PAGE',
published_version: 1,
version: 1,
course_id: course.id,
});
setIsSubmitting(false);
};
})
setIsSubmitting(false)
}
return (
<FormLayout onSubmit={handleSubmit}>
<FormField name="dynamic-activity-name">
<Flex css={{ alignItems: 'baseline', justifyContent: 'space-between' }}>
<FormLabel>Activity name</FormLabel>
<FormMessage match="valueMissing">Please provide a name for your activity</FormMessage>
<FormMessage match="valueMissing">
Please provide a name for your activity
</FormMessage>
</Flex>
<Form.Control asChild>
<Input onChange={handleActivityNameChange} type="text" required />
@ -44,7 +54,9 @@ function DynamicCanvaModal({ submitActivity, chapterId, course }: any) {
<FormField name="dynamic-activity-desc">
<Flex css={{ alignItems: 'baseline', justifyContent: 'space-between' }}>
<FormLabel>Activity description</FormLabel>
<FormMessage match="valueMissing">Please provide a description for your activity</FormMessage>
<FormMessage match="valueMissing">
Please provide a description for your activity
</FormMessage>
</Flex>
<Form.Control asChild>
<Textarea onChange={handleActivityDescriptionChange} required />
@ -53,14 +65,21 @@ function DynamicCanvaModal({ submitActivity, chapterId, course }: any) {
<Flex css={{ marginTop: 25, justifyContent: 'flex-end' }}>
<Form.Submit asChild>
<ButtonBlack type="submit" css={{ marginTop: 10 }}>
{isSubmitting ? <BarLoader cssOverride={{borderRadius:60,}} width={60} color="#ffffff" />
: "Create activity"}
<ButtonBlack type="submit" css={{ marginTop: 10 }}>
{isSubmitting ? (
<BarLoader
cssOverride={{ borderRadius: 60 }}
width={60}
color="#ffffff"
/>
) : (
'Create activity'
)}
</ButtonBlack>
</Form.Submit>
</Flex>
</FormLayout>
);
)
}
export default DynamicCanvaModal;
export default DynamicCanvaModal

View file

@ -1,67 +1,87 @@
import FormLayout, { ButtonBlack, Flex, FormField, FormLabel, FormMessage, Input } from "@components/StyledElements/Form/Form";
import React, { useState } from "react";
import * as Form from '@radix-ui/react-form';
import BarLoader from "react-spinners/BarLoader";
import { Youtube } from "lucide-react";
import FormLayout, {
ButtonBlack,
Flex,
FormField,
FormLabel,
FormMessage,
Input,
} from '@components/StyledElements/Form/Form'
import React, { useState } from 'react'
import * as Form from '@radix-ui/react-form'
import BarLoader from 'react-spinners/BarLoader'
import { Youtube } from 'lucide-react'
interface ExternalVideoObject {
name: string,
type: string,
name: string
type: string
uri: string
chapter_id: string
}
function VideoModal({ submitFileActivity, submitExternalVideo, chapterId, course }: any) {
const [video, setVideo] = React.useState(null) as any;
const [isSubmitting, setIsSubmitting] = useState(false);
const [name, setName] = React.useState("");
const [youtubeUrl, setYoutubeUrl] = React.useState("");
const [selectedView, setSelectedView] = React.useState("file") as any;
function VideoModal({
submitFileActivity,
submitExternalVideo,
chapterId,
course,
}: any) {
const [video, setVideo] = React.useState(null) as any
const [isSubmitting, setIsSubmitting] = useState(false)
const [name, setName] = React.useState('')
const [youtubeUrl, setYoutubeUrl] = React.useState('')
const [selectedView, setSelectedView] = React.useState('file') as any
const handleVideoChange = (event: React.ChangeEvent<any>) => {
setVideo(event.target.files[0]);
};
setVideo(event.target.files[0])
}
const handleNameChange = (event: React.ChangeEvent<HTMLInputElement>) => {
setName(event.target.value);
};
setName(event.target.value)
}
const handleYoutubeUrlChange = (event: React.ChangeEvent<HTMLInputElement>) => {
setYoutubeUrl(event.target.value);
};
const handleYoutubeUrlChange = (
event: React.ChangeEvent<HTMLInputElement>
) => {
setYoutubeUrl(event.target.value)
}
const handleSubmit = async (e: any) => {
e.preventDefault();
setIsSubmitting(true);
e.preventDefault()
setIsSubmitting(true)
if (selectedView === "file") {
let status = await submitFileActivity(video, "video", {
name: name,
chapter_id: chapterId,
activity_type: "TYPE_VIDEO",
activity_sub_type: "SUBTYPE_VIDEO_HOSTED",
published_version: 1,
version: 1,
course_id: course.id,
}, chapterId);
if (selectedView === 'file') {
let status = await submitFileActivity(
video,
'video',
{
name: name,
chapter_id: chapterId,
activity_type: 'TYPE_VIDEO',
activity_sub_type: 'SUBTYPE_VIDEO_HOSTED',
published_version: 1,
version: 1,
course_id: course.id,
},
chapterId
)
setIsSubmitting(false);
setIsSubmitting(false)
}
if (selectedView === "youtube") {
if (selectedView === 'youtube') {
let external_video_object: ExternalVideoObject = {
name,
type: "youtube",
type: 'youtube',
uri: youtubeUrl,
chapter_id: chapterId
chapter_id: chapterId,
}
let status = await submitExternalVideo(external_video_object, 'activity', chapterId);
setIsSubmitting(false);
let status = await submitExternalVideo(
external_video_object,
'activity',
chapterId
)
setIsSubmitting(false)
}
};
}
/* TODO : implement some sort of progress bar for file uploads, it is not possible yet because i'm not using axios.
and the actual upload isn't happening here anyway, it's in the submitFileActivity function */
@ -71,7 +91,9 @@ function VideoModal({ submitFileActivity, submitExternalVideo, chapterId, course
<FormField name="video-activity-name">
<Flex css={{ alignItems: 'baseline', justifyContent: 'space-between' }}>
<FormLabel>Video name</FormLabel>
<FormMessage match="valueMissing">Please provide a name for your video activity</FormMessage>
<FormMessage match="valueMissing">
Please provide a name for your video activity
</FormMessage>
</Flex>
<Form.Control asChild>
<Input onChange={handleNameChange} type="text" required />
@ -80,29 +102,67 @@ function VideoModal({ submitFileActivity, submitExternalVideo, chapterId, course
<div className="flex flex-col rounded-md bg-gray-50 outline-dashed outline-gray-200">
<div className="">
<div className="flex m-4 justify-center space-x-2 mb-0">
<div onClick={() => { setSelectedView("file") }} className="rounded-full bg-slate-900 text-zinc-50 py-2 px-4 text-sm drop-shadow-md hover:cursor-pointer hover:bg-slate-700 ">Video upload</div>
<div onClick={() => { setSelectedView("youtube") }} className="rounded-full bg-slate-900 text-zinc-50 py-2 px-4 text-sm drop-shadow-md hover:cursor-pointer hover:bg-slate-700">YouTube Video</div>
<div
onClick={() => {
setSelectedView('file')
}}
className="rounded-full bg-slate-900 text-zinc-50 py-2 px-4 text-sm drop-shadow-md hover:cursor-pointer hover:bg-slate-700 "
>
Video upload
</div>
<div
onClick={() => {
setSelectedView('youtube')
}}
className="rounded-full bg-slate-900 text-zinc-50 py-2 px-4 text-sm drop-shadow-md hover:cursor-pointer hover:bg-slate-700"
>
YouTube Video
</div>
</div>
{selectedView === "file" && (<div className="p-4 justify-center m-auto align-middle">
<FormField name="video-activity-file">
<Flex css={{ alignItems: 'baseline', justifyContent: 'space-between' }}>
<FormLabel>Video file</FormLabel>
<FormMessage match="valueMissing">Please provide a video for your activity</FormMessage>
</Flex>
<Form.Control asChild>
<input type="file" onChange={handleVideoChange} required />
</Form.Control>
</FormField>
</div>)}
{selectedView === "youtube" && (
{selectedView === 'file' && (
<div className="p-4 justify-center m-auto align-middle">
<FormField name="video-activity-file">
<Flex css={{ alignItems: 'baseline', justifyContent: 'space-between' }}>
<FormLabel className="flex justify-center align-middle"><Youtube className="m-auto pr-1" /><span className="flex">YouTube URL</span></FormLabel>
<FormMessage match="valueMissing">Please provide a video for your activity</FormMessage>
<Flex
css={{
alignItems: 'baseline',
justifyContent: 'space-between',
}}
>
<FormLabel>Video file</FormLabel>
<FormMessage match="valueMissing">
Please provide a video for your activity
</FormMessage>
</Flex>
<Form.Control asChild>
<Input className="bg-white" onChange={handleYoutubeUrlChange} type="text" required />
<input type="file" onChange={handleVideoChange} required />
</Form.Control>
</FormField>
</div>
)}
{selectedView === 'youtube' && (
<div className="p-4 justify-center m-auto align-middle">
<FormField name="video-activity-file">
<Flex
css={{
alignItems: 'baseline',
justifyContent: 'space-between',
}}
>
<FormLabel className="flex justify-center align-middle">
<Youtube className="m-auto pr-1" />
<span className="flex">YouTube URL</span>
</FormLabel>
<FormMessage match="valueMissing">
Please provide a video for your activity
</FormMessage>
</Flex>
<Form.Control asChild>
<Input
className="bg-white"
onChange={handleYoutubeUrlChange}
type="text"
required
/>
</Form.Control>
</FormField>
</div>
@ -112,13 +172,25 @@ function VideoModal({ submitFileActivity, submitExternalVideo, chapterId, course
<Flex css={{ marginTop: 25, justifyContent: 'flex-end' }}>
<Form.Submit asChild>
<ButtonBlack className="bg-black" type="submit" css={{ marginTop: 10 }}>
{isSubmitting ? <BarLoader cssOverride={{ borderRadius: 60, }} width={60} color="#ffffff" /> : "Create activity"}
<ButtonBlack
className="bg-black"
type="submit"
css={{ marginTop: 10 }}
>
{isSubmitting ? (
<BarLoader
cssOverride={{ borderRadius: 60 }}
width={60}
color="#ffffff"
/>
) : (
'Create activity'
)}
</ButtonBlack>
</Form.Submit>
</Flex>
</FormLayout>
);
)
}
export default VideoModal;
export default VideoModal

View file

@ -1,44 +1,52 @@
import FormLayout, { Flex, FormField, Input, Textarea, FormLabel, ButtonBlack } from "@components/StyledElements/Form/Form";
import { FormMessage } from "@radix-ui/react-form";
import * as Form from '@radix-ui/react-form';
import React, { useState } from "react";
import BarLoader from "react-spinners/BarLoader";
import FormLayout, {
Flex,
FormField,
Input,
Textarea,
FormLabel,
ButtonBlack,
} from '@components/StyledElements/Form/Form'
import { FormMessage } from '@radix-ui/react-form'
import * as Form from '@radix-ui/react-form'
import React, { useState } from 'react'
import BarLoader from 'react-spinners/BarLoader'
function NewChapterModal({ submitChapter, closeModal, course }: any) {
const [chapterName, setChapterName] = useState("");
const [chapterDescription, setChapterDescription] = useState("");
const [isSubmitting, setIsSubmitting] = useState(false);
const [chapterName, setChapterName] = useState('')
const [chapterDescription, setChapterDescription] = useState('')
const [isSubmitting, setIsSubmitting] = useState(false)
const handleChapterNameChange = (e: any) => {
setChapterName(e.target.value);
};
setChapterName(e.target.value)
}
const handleChapterDescriptionChange = (e: any) => {
setChapterDescription(e.target.value);
};
setChapterDescription(e.target.value)
}
const handleSubmit = async (e: any) => {
e.preventDefault();
e.preventDefault()
setIsSubmitting(true);
setIsSubmitting(true)
const chapter_object = {
name: chapterName,
description: chapterDescription,
thumbnail_image: "",
thumbnail_image: '',
course_id: course.id,
org_id: course.org_id
};
await submitChapter(chapter_object);
setIsSubmitting(false);
};
org_id: course.org_id,
}
await submitChapter(chapter_object)
setIsSubmitting(false)
}
return (
<FormLayout onSubmit={handleSubmit}>
<FormField name="chapter-name">
<Flex css={{ alignItems: 'baseline', justifyContent: 'space-between' }}>
<FormLabel>Chapter name</FormLabel>
<FormMessage match="valueMissing">Please provide a chapter name</FormMessage>
<FormMessage match="valueMissing">
Please provide a chapter name
</FormMessage>
</Flex>
<Form.Control asChild>
<Input onChange={handleChapterNameChange} type="text" required />
@ -47,7 +55,9 @@ function NewChapterModal({ submitChapter, closeModal, course }: any) {
<FormField name="chapter-desc">
<Flex css={{ alignItems: 'baseline', justifyContent: 'space-between' }}>
<FormLabel>Chapter description</FormLabel>
<FormMessage match="valueMissing">Please provide a chapter description</FormMessage>
<FormMessage match="valueMissing">
Please provide a chapter description
</FormMessage>
</Flex>
<Form.Control asChild>
<Textarea onChange={handleChapterDescriptionChange} required />
@ -57,13 +67,20 @@ function NewChapterModal({ submitChapter, closeModal, course }: any) {
<Flex css={{ marginTop: 25, justifyContent: 'flex-end' }}>
<Form.Submit asChild>
<ButtonBlack type="submit" css={{ marginTop: 10 }}>
{isSubmitting ? <BarLoader cssOverride={{ borderRadius: 60, }} width={60} color="#ffffff" />
: "Create Chapter"}
{isSubmitting ? (
<BarLoader
cssOverride={{ borderRadius: 60 }}
width={60}
color="#ffffff"
/>
) : (
'Create Chapter'
)}
</ButtonBlack>
</Form.Submit>
</Flex>
</FormLayout>
);
)
}
export default NewChapterModal;
export default NewChapterModal

View file

@ -1,151 +1,183 @@
'use client';
import FormLayout, { ButtonBlack, Flex, FormField, FormLabel, Input, Textarea } from '@components/StyledElements/Form/Form'
'use client'
import FormLayout, {
ButtonBlack,
Flex,
FormField,
FormLabel,
Input,
Textarea,
} from '@components/StyledElements/Form/Form'
import * as Form from '@radix-ui/react-form'
import { FormMessage } from "@radix-ui/react-form";
import { createNewCourse } from '@services/courses/courses';
import { getOrganizationContextInfoWithoutCredentials } from '@services/organizations/orgs';
import { FormMessage } from '@radix-ui/react-form'
import { createNewCourse } from '@services/courses/courses'
import { getOrganizationContextInfoWithoutCredentials } from '@services/organizations/orgs'
import React, { useState } from 'react'
import { BarLoader } from 'react-spinners'
import { revalidateTags } from '@services/utils/ts/requests';
import { useRouter } from 'next/navigation';
import { revalidateTags } from '@services/utils/ts/requests'
import { useRouter } from 'next/navigation'
function CreateCourseModal({ closeModal, orgslug }: any) {
const [isSubmitting, setIsSubmitting] = useState(false);
const [name, setName] = React.useState("");
const [description, setDescription] = React.useState("");
const [learnings, setLearnings] = React.useState("");
const [visibility, setVisibility] = React.useState(true);
const [tags, setTags] = React.useState("");
const [isLoading, setIsLoading] = React.useState(false);
const [thumbnail, setThumbnail] = React.useState(null) as any;
const router = useRouter();
const [isSubmitting, setIsSubmitting] = useState(false)
const [name, setName] = React.useState('')
const [description, setDescription] = React.useState('')
const [learnings, setLearnings] = React.useState('')
const [visibility, setVisibility] = React.useState(true)
const [tags, setTags] = React.useState('')
const [isLoading, setIsLoading] = React.useState(false)
const [thumbnail, setThumbnail] = React.useState(null) as any
const router = useRouter()
const [orgId, setOrgId] = React.useState(null) as any;
const [org, setOrg] = React.useState(null) as any;
const [orgId, setOrgId] = React.useState(null) as any
const [org, setOrg] = React.useState(null) as any
const getOrgMetadata = async () => {
const org = await getOrganizationContextInfoWithoutCredentials(orgslug, {
revalidate: 360,
tags: ['organizations'],
})
const getOrgMetadata = async () => {
const org = await getOrganizationContextInfoWithoutCredentials(orgslug, { revalidate: 360, tags: ['organizations'] });
setOrgId(org.id)
}
setOrgId(org.id);
}
const handleNameChange = (event: React.ChangeEvent<HTMLInputElement>) => {
setName(event.target.value)
}
const handleDescriptionChange = (event: React.ChangeEvent<any>) => {
setDescription(event.target.value)
}
const handleNameChange = (event: React.ChangeEvent<HTMLInputElement>) => {
setName(event.target.value);
};
const handleLearningsChange = (event: React.ChangeEvent<any>) => {
setLearnings(event.target.value)
}
const handleDescriptionChange = (event: React.ChangeEvent<any>) => {
setDescription(event.target.value);
};
const handleVisibilityChange = (event: React.ChangeEvent<any>) => {
setVisibility(event.target.value)
console.log(visibility)
}
const handleLearningsChange = (event: React.ChangeEvent<any>) => {
setLearnings(event.target.value);
}
const handleTagsChange = (event: React.ChangeEvent<any>) => {
setTags(event.target.value)
}
const handleVisibilityChange = (event: React.ChangeEvent<any>) => {
setVisibility(event.target.value);
console.log(visibility);
}
const handleThumbnailChange = (event: React.ChangeEvent<any>) => {
setThumbnail(event.target.files[0])
}
const handleTagsChange = (event: React.ChangeEvent<any>) => {
setTags(event.target.value);
}
const handleSubmit = async (e: any) => {
e.preventDefault()
setIsSubmitting(true)
const handleThumbnailChange = (event: React.ChangeEvent<any>) => {
setThumbnail(event.target.files[0]);
};
const handleSubmit = async (e: any) => {
e.preventDefault();
setIsSubmitting(true);
let status = await createNewCourse(orgId, { name, description, tags, visibility }, thumbnail);
await revalidateTags(['courses'], orgslug);
setIsSubmitting(false);
if (status.org_id == orgId) {
closeModal();
router.refresh();
await revalidateTags(['courses'], orgslug);
// refresh page (FIX for Next.js BUG)
// window.location.reload();
} else {
alert("Error creating course, please see console logs");
}
};
React.useEffect(() => {
if (orgslug) {
getOrgMetadata();
}
}, [isLoading, orgslug]);
return (
<FormLayout onSubmit={handleSubmit}>
<FormField name="course-name">
<Flex css={{ alignItems: 'baseline', justifyContent: 'space-between' }}>
<FormLabel>Course name</FormLabel>
<FormMessage match="valueMissing">Please provide a course name</FormMessage>
</Flex>
<Form.Control asChild>
<Input onChange={handleNameChange} type="text" required />
</Form.Control>
</FormField>
<FormField name="course-desc">
<Flex css={{ alignItems: 'baseline', justifyContent: 'space-between' }}>
<FormLabel>Course description</FormLabel>
<FormMessage match="valueMissing">Please provide a course description</FormMessage>
</Flex>
<Form.Control asChild>
<Textarea onChange={handleDescriptionChange} required />
</Form.Control>
</FormField>
<FormField name="course-thumbnail">
<Flex css={{ alignItems: 'baseline', justifyContent: 'space-between' }}>
<FormLabel>Course thumbnail</FormLabel>
<FormMessage match="valueMissing">Please provide a thumbnail for your course</FormMessage>
</Flex>
<Form.Control asChild>
<Input onChange={handleThumbnailChange} type="file" />
</Form.Control>
</FormField>
<FormField name="course-tags">
<Flex css={{ alignItems: 'baseline', justifyContent: 'space-between' }}>
<FormLabel>Course Learnings (separated by comma)</FormLabel>
<FormMessage match="valueMissing">Please provide learning elements, separated by comma (,)</FormMessage>
</Flex>
<Form.Control asChild>
<Textarea onChange={handleTagsChange} />
</Form.Control>
</FormField>
<FormField name="course-visibility">
<Flex css={{ alignItems: 'baseline', justifyContent: 'space-between' }}>
<FormLabel>Course Visibility</FormLabel>
<FormMessage match="valueMissing">Please choose course visibility</FormMessage>
</Flex>
<Form.Control asChild>
<select onChange={handleVisibilityChange} className='border border-gray-300 rounded-md p-2' required>
<option value="true">Public (Available to see on the internet) </option>
<option value="false">Private (Private to users) </option>
</select>
</Form.Control>
</FormField>
<Flex css={{ marginTop: 25, justifyContent: 'flex-end' }}>
<Form.Submit asChild>
<ButtonBlack type="submit" css={{ marginTop: 10 }}>
{isSubmitting ? <BarLoader cssOverride={{ borderRadius: 60, }} width={60} color="#ffffff" />
: "Create Course"}
</ButtonBlack>
</Form.Submit>
</Flex>
</FormLayout>
let status = await createNewCourse(
orgId,
{ name, description, tags, visibility },
thumbnail
)
await revalidateTags(['courses'], orgslug)
setIsSubmitting(false)
if (status.org_id == orgId) {
closeModal()
router.refresh()
await revalidateTags(['courses'], orgslug)
// refresh page (FIX for Next.js BUG)
// window.location.reload();
} else {
alert('Error creating course, please see console logs')
}
}
React.useEffect(() => {
if (orgslug) {
getOrgMetadata()
}
}, [isLoading, orgslug])
return (
<FormLayout onSubmit={handleSubmit}>
<FormField name="course-name">
<Flex css={{ alignItems: 'baseline', justifyContent: 'space-between' }}>
<FormLabel>Course name</FormLabel>
<FormMessage match="valueMissing">
Please provide a course name
</FormMessage>
</Flex>
<Form.Control asChild>
<Input onChange={handleNameChange} type="text" required />
</Form.Control>
</FormField>
<FormField name="course-desc">
<Flex css={{ alignItems: 'baseline', justifyContent: 'space-between' }}>
<FormLabel>Course description</FormLabel>
<FormMessage match="valueMissing">
Please provide a course description
</FormMessage>
</Flex>
<Form.Control asChild>
<Textarea onChange={handleDescriptionChange} required />
</Form.Control>
</FormField>
<FormField name="course-thumbnail">
<Flex css={{ alignItems: 'baseline', justifyContent: 'space-between' }}>
<FormLabel>Course thumbnail</FormLabel>
<FormMessage match="valueMissing">
Please provide a thumbnail for your course
</FormMessage>
</Flex>
<Form.Control asChild>
<Input onChange={handleThumbnailChange} type="file" />
</Form.Control>
</FormField>
<FormField name="course-tags">
<Flex css={{ alignItems: 'baseline', justifyContent: 'space-between' }}>
<FormLabel>Course Learnings (separated by comma)</FormLabel>
<FormMessage match="valueMissing">
Please provide learning elements, separated by comma (,)
</FormMessage>
</Flex>
<Form.Control asChild>
<Textarea onChange={handleTagsChange} />
</Form.Control>
</FormField>
<FormField name="course-visibility">
<Flex css={{ alignItems: 'baseline', justifyContent: 'space-between' }}>
<FormLabel>Course Visibility</FormLabel>
<FormMessage match="valueMissing">
Please choose course visibility
</FormMessage>
</Flex>
<Form.Control asChild>
<select
onChange={handleVisibilityChange}
className="border border-gray-300 rounded-md p-2"
required
>
<option value="true">
Public (Available to see on the internet){' '}
</option>
<option value="false">Private (Private to users) </option>
</select>
</Form.Control>
</FormField>
<Flex css={{ marginTop: 25, justifyContent: 'flex-end' }}>
<Form.Submit asChild>
<ButtonBlack type="submit" css={{ marginTop: 10 }}>
{isSubmitting ? (
<BarLoader
cssOverride={{ borderRadius: 60 }}
width={60}
color="#ffffff"
/>
) : (
'Create Course'
)}
</ButtonBlack>
</Form.Submit>
</Flex>
</FormLayout>
)
}
export default CreateCourseModal
export default CreateCourseModal

View file

@ -1,81 +1,105 @@
'use client';
import { useOrg } from '@components/Contexts/OrgContext';
import FormLayout, { ButtonBlack, Flex, FormField, FormLabel } from '@components/StyledElements/Form/Form'
'use client'
import { useOrg } from '@components/Contexts/OrgContext'
import FormLayout, {
ButtonBlack,
Flex,
FormField,
FormLabel,
} from '@components/StyledElements/Form/Form'
import * as Form from '@radix-ui/react-form'
import { FormMessage } from "@radix-ui/react-form";
import { getAPIUrl } from '@services/config/config';
import { updateUserRole } from '@services/organizations/orgs';
import { FormMessage } from '@radix-ui/react-form'
import { getAPIUrl } from '@services/config/config'
import { updateUserRole } from '@services/organizations/orgs'
import React, { useEffect } from 'react'
import { BarLoader } from 'react-spinners';
import { mutate } from 'swr';
import { BarLoader } from 'react-spinners'
import { mutate } from 'swr'
interface Props {
user: any
setRolesModal: any
alreadyAssignedRole: any
user: any
setRolesModal: any
alreadyAssignedRole: any
}
function RolesUpdate(props: Props) {
const org = useOrg() as any;
const [isSubmitting, setIsSubmitting] = React.useState(false);
const [assignedRole, setAssignedRole] = React.useState(props.alreadyAssignedRole);
const [error, setError] = React.useState(null) as any;
const org = useOrg() as any
const [isSubmitting, setIsSubmitting] = React.useState(false)
const [assignedRole, setAssignedRole] = React.useState(
props.alreadyAssignedRole
)
const [error, setError] = React.useState(null) as any
const handleAssignedRole = (event: React.ChangeEvent<any>) => {
setError(null);
setAssignedRole(event.target.value);
const handleAssignedRole = (event: React.ChangeEvent<any>) => {
setError(null)
setAssignedRole(event.target.value)
}
const handleSubmit = async (e: any) => {
e.preventDefault()
setIsSubmitting(true)
const res = await updateUserRole(org.id, props.user.user.id, assignedRole)
if (res.status === 200) {
await mutate(`${getAPIUrl()}orgs/${org.id}/users`)
props.setRolesModal(false)
} else {
setIsSubmitting(false)
setError('Error ' + res.status + ': ' + res.data.detail)
}
}
const handleSubmit = async (e: any) => {
e.preventDefault();
setIsSubmitting(true);
const res = await updateUserRole(org.id, props.user.user.id, assignedRole);
useEffect(() => {}, [assignedRole])
if (res.status === 200) {
await mutate(`${getAPIUrl()}orgs/${org.id}/users`);
props.setRolesModal(false);
}
else {
setIsSubmitting(false);
setError('Error ' + res.status + ': ' + res.data.detail);
}
};
useEffect(() => {
}
, [assignedRole])
return (
<div>
<FormLayout onSubmit={handleSubmit}>
<FormField name="course-visibility">
{error ? <div className='text-red-500 font-bold text-xs px-3 py-2 bg-red-100 rounded-md'>{error}</div> : ''}
<Flex css={{ alignItems: 'baseline', justifyContent: 'space-between' }}>
<FormLabel>Roles</FormLabel>
<FormMessage match="valueMissing">Please choose a role for the user</FormMessage>
</Flex>
<Form.Control asChild>
<select onChange={handleAssignedRole} defaultValue={assignedRole} className='border border-gray-300 rounded-md p-2' required>
<option value="role_global_admin">Admin </option>
<option value="role_global_maintainer">Maintainer</option>
<option value="role_global_user">User</option>
</select>
</Form.Control>
</FormField>
<div className='h-full'></div>
<Flex css={{ marginTop: 25, justifyContent: 'flex-end' }}>
<Form.Submit asChild>
<ButtonBlack type="submit" css={{ marginTop: 10 }}>
{isSubmitting ? <BarLoader cssOverride={{ borderRadius: 60, }} width={60} color="#ffffff" />
: "Update user role"}
</ButtonBlack>
</Form.Submit>
</Flex>
</FormLayout>
</div>
)
return (
<div>
<FormLayout onSubmit={handleSubmit}>
<FormField name="course-visibility">
{error ? (
<div className="text-red-500 font-bold text-xs px-3 py-2 bg-red-100 rounded-md">
{error}
</div>
) : (
''
)}
<Flex
css={{ alignItems: 'baseline', justifyContent: 'space-between' }}
>
<FormLabel>Roles</FormLabel>
<FormMessage match="valueMissing">
Please choose a role for the user
</FormMessage>
</Flex>
<Form.Control asChild>
<select
onChange={handleAssignedRole}
defaultValue={assignedRole}
className="border border-gray-300 rounded-md p-2"
required
>
<option value="role_global_admin">Admin </option>
<option value="role_global_maintainer">Maintainer</option>
<option value="role_global_user">User</option>
</select>
</Form.Control>
</FormField>
<div className="h-full"></div>
<Flex css={{ marginTop: 25, justifyContent: 'flex-end' }}>
<Form.Submit asChild>
<ButtonBlack type="submit" css={{ marginTop: 10 }}>
{isSubmitting ? (
<BarLoader
cssOverride={{ borderRadius: 60 }}
width={60}
color="#ffffff"
/>
) : (
'Update user role'
)}
</ButtonBlack>
</Form.Submit>
</Flex>
</FormLayout>
</div>
)
}
export default RolesUpdate
export default RolesUpdate

View file

@ -1,87 +1,111 @@
import FormLayout, { ButtonBlack, Flex, FormField, FormLabel, FormMessage, Textarea } from "@components/StyledElements/Form/Form"
import { BarLoader } from "react-spinners"
import FormLayout, {
ButtonBlack,
Flex,
FormField,
FormLabel,
FormMessage,
Textarea,
} from '@components/StyledElements/Form/Form'
import { BarLoader } from 'react-spinners'
import * as Form from '@radix-ui/react-form'
import React, { useState } from "react";
import * as Sentry from '@sentry/browser';
import { CheckCircleIcon } from "lucide-react";
import { useSession } from "@components/Contexts/SessionContext";
import React, { useState } from 'react'
import * as Sentry from '@sentry/browser'
import { CheckCircleIcon } from 'lucide-react'
import { useSession } from '@components/Contexts/SessionContext'
export const FeedbackModal = (user: any) => {
const session = useSession() as any;
const session = useSession() as any
const [isSubmitting, setIsSubmitting] = useState(false);
const [view, setView] = useState<"feedbackForm" | "success">("feedbackForm")
const [feedbackMessage, setFeedbackMessage] = useState("");
const [isSubmitting, setIsSubmitting] = useState(false)
const [view, setView] = useState<'feedbackForm' | 'success'>('feedbackForm')
const [feedbackMessage, setFeedbackMessage] = useState('')
const handleSubmit = async (e: any) => {
e.preventDefault()
setIsSubmitting(true)
const handleSubmit = async (e: any) => {
e.preventDefault();
setIsSubmitting(true);
const user = session.user ? session.user : null
const eventId = Sentry.captureMessage(
`Feedback from ${user ? user.email : 'Anonymous'} - ${feedbackMessage}`
)
const user = session.user ? session.user : null;
const eventId = Sentry.captureMessage(`Feedback from ${user ? user.email : 'Anonymous'} - ${feedbackMessage}`);
const userFeedback = {
event_id: eventId,
name: user ? user.full_name : 'Anonymous',
email: user ? user.email : 'Anonymous',
comments: feedbackMessage,
}
Sentry.captureUserFeedback(userFeedback);
setIsSubmitting(false);
setView("success");
};
const handleFeedbackMessage = (event: React.ChangeEvent<any>) => {
setFeedbackMessage(event.target.value)
};
if (view == "feedbackForm") {
return (
<FormLayout onSubmit={handleSubmit}>
<FormField name="feedback-message">
<Flex css={{ alignItems: 'baseline', justifyContent: 'space-between' }}>
<FormLabel>Feedback message</FormLabel>
<FormMessage match="valueMissing">Please provide learning elements, separated by comma (,)</FormMessage>
</Flex>
<Form.Control asChild>
<Textarea style={{ height: 150, }} onChange={handleFeedbackMessage} required />
</Form.Control>
</FormField>
<Flex css={{ marginTop: 25, justifyContent: 'flex-end' }}>
<Form.Submit asChild>
<ButtonBlack type="submit" css={{ marginTop: 10 }}>
{isSubmitting ? <BarLoader cssOverride={{ borderRadius: 60, }} width={60} color="#ffffff" />
: "Submit Feedback"}
</ButtonBlack>
</Form.Submit>
</Flex>
</FormLayout>
)
} else {
return (
<div className="flex flex-col items-center space-y-5">
<div className="flex flex-col items-center space-y-5 pt-10">
<div className="flex items-center space-x-2">
<div className="text-9xl text-green-500">
<CheckCircleIcon></CheckCircleIcon>
</div>
<div className="text-3xl text-green-500">
<div>Thank you for your feedback!</div>
</div>
</div>
<div className="text-xl text-gray-500">
<div>We will take it into account.</div>
</div>
</div>
<div className="flex items-center space-x-2">
<ButtonBlack onClick={() => setView("feedbackForm")}>Send another feedback</ButtonBlack>
</div>
</div>
)
const userFeedback = {
event_id: eventId,
name: user ? user.full_name : 'Anonymous',
email: user ? user.email : 'Anonymous',
comments: feedbackMessage,
}
Sentry.captureUserFeedback(userFeedback)
setIsSubmitting(false)
setView('success')
}
const handleFeedbackMessage = (event: React.ChangeEvent<any>) => {
setFeedbackMessage(event.target.value)
}
if (view == 'feedbackForm') {
return (
<FormLayout onSubmit={handleSubmit}>
<FormField name="feedback-message">
<Flex
css={{ alignItems: 'baseline', justifyContent: 'space-between' }}
>
<FormLabel>Feedback message</FormLabel>
<FormMessage match="valueMissing">
Please provide learning elements, separated by comma (,)
</FormMessage>
</Flex>
<Form.Control asChild>
<Textarea
style={{ height: 150 }}
onChange={handleFeedbackMessage}
required
/>
</Form.Control>
</FormField>
<Flex css={{ marginTop: 25, justifyContent: 'flex-end' }}>
<Form.Submit asChild>
<ButtonBlack type="submit" css={{ marginTop: 10 }}>
{isSubmitting ? (
<BarLoader
cssOverride={{ borderRadius: 60 }}
width={60}
color="#ffffff"
/>
) : (
'Submit Feedback'
)}
</ButtonBlack>
</Form.Submit>
</Flex>
</FormLayout>
)
} else {
return (
<div className="flex flex-col items-center space-y-5">
<div className="flex flex-col items-center space-y-5 pt-10">
<div className="flex items-center space-x-2">
<div className="text-9xl text-green-500">
<CheckCircleIcon></CheckCircleIcon>
</div>
<div className="text-3xl text-green-500">
<div>Thank you for your feedback!</div>
</div>
</div>
<div className="text-xl text-gray-500">
<div>We will take it into account.</div>
</div>
</div>
<div className="flex items-center space-x-2">
<ButtonBlack onClick={() => setView('feedbackForm')}>
Send another feedback
</ButtonBlack>
</div>
</div>
)
}
}
export default FeedbackModal
export default FeedbackModal