diff --git a/front/components/modals/CourseEdit/NewElement.tsx b/front/components/modals/CourseEdit/NewElement.tsx index 6903a210..e8a0f4ae 100644 --- a/front/components/modals/CourseEdit/NewElement.tsx +++ b/front/components/modals/CourseEdit/NewElement.tsx @@ -1,39 +1,62 @@ import React, { useState } from "react"; +import { ArrowLeftIcon, Cross1Icon } from "@radix-ui/react-icons"; import Modal from "../Modal"; +import styled from "styled-components"; +import dynamic from "next/dynamic"; +import DynamicCanvaModal from "./NewElementModal/DynamicCanva"; +import VideoModal from "./NewElementModal/Video"; -function NewElementModal({ closeModal, submitElement, chapterId }: any) { - const [elementName, setElementName] = useState(""); - const [elementDescription, setElementDescription] = useState(""); - - const handleElementNameChange = (e: any) => { - setElementName(e.target.value); - }; - - const handleElementDescriptionChange = (e: any) => { - setElementDescription(e.target.value); - }; - - const handleSubmit = async (e: any) => { - e.preventDefault(); - console.log({ elementName, elementDescription, chapterId }); - submitElement({ - name: elementName, - chapterId: chapterId, - type: "dynamic", - }); - }; +function NewElementModal({ closeModal, submitElement, submitFileElement, chapterId }: any) { + const [selectedView, setSelectedView] = useState("home"); return ( -

- Add New Element -

-
- + + +

Add New Element


- + + {selectedView === "home" && ( + + {setSelectedView("dynamic")}}>✨📄 + {setSelectedView("video")}}>📹 + + )} + + {selectedView === "dynamic" && ( + + )} + + {selectedView === "video" && ( + + )} +
); } +const ElementChooserWrapper = styled.div` + display: flex; + flex-direction: row; + align-items: center; + justify-content: center; + gap: 20px; +`; + +const ElementButton = styled.button` + padding: 20px; + border-radius: 10px; + border: none; + font-size: 50px; + background-color: #8c949c33; + cursor: pointer; + &:hover { + background-color: #8c949c7b; + } +`; + export default NewElementModal; diff --git a/front/components/modals/CourseEdit/NewElementModal/DynamicCanva.tsx b/front/components/modals/CourseEdit/NewElementModal/DynamicCanva.tsx new file mode 100644 index 00000000..5caf5577 --- /dev/null +++ b/front/components/modals/CourseEdit/NewElementModal/DynamicCanva.tsx @@ -0,0 +1,36 @@ +import React, { useState } from "react"; + +function DynamicCanvaModal({ submitElement, chapterId }: any) { + const [elementName, setElementName] = useState(""); + const [elementDescription, setElementDescription] = useState(""); + + const handleElementNameChange = (e: any) => { + setElementName(e.target.value); + }; + + const handleElementDescriptionChange = (e: any) => { + setElementDescription(e.target.value); + }; + + const handleSubmit = async (e: any) => { + e.preventDefault(); + console.log({ elementName, elementDescription, chapterId }); + submitElement({ + name: elementName, + chapterId: chapterId, + type: "dynamic", + }); + }; + return ( +
+
+
+ +
+ +
+
+ ); +} + +export default DynamicCanvaModal; diff --git a/front/components/modals/CourseEdit/NewElementModal/Video.tsx b/front/components/modals/CourseEdit/NewElementModal/Video.tsx new file mode 100644 index 00000000..fce8f192 --- /dev/null +++ b/front/components/modals/CourseEdit/NewElementModal/Video.tsx @@ -0,0 +1,37 @@ +import React from "react"; + +function VideoModal({ submitFileElement, chapterId }: any) { + const [video, setVideo] = React.useState(null) as any; + const [name, setName] = React.useState(""); + + const handleVideoChange = (event: React.ChangeEvent) => { + setVideo(event.target.files[0]); + }; + + const handleNameChange = (event: React.ChangeEvent) => { + setName(event.target.value); + }; + + const handleSubmit = async (e: any) => { + e.preventDefault(); + let status = await submitFileElement(video, "video", { name, type: "video" }, chapterId); + }; + + /* 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 submitFileElement function */ + + return ( +
+ +
+
+ +
+ +
+ +
+ ); +} + +export default VideoModal; diff --git a/front/pages/org/[orgslug]/course/[courseid]/edit/index.tsx b/front/pages/org/[orgslug]/course/[courseid]/edit/index.tsx index 50f0e1d2..17574061 100644 --- a/front/pages/org/[orgslug]/course/[courseid]/edit/index.tsx +++ b/front/pages/org/[orgslug]/course/[courseid]/edit/index.tsx @@ -11,7 +11,7 @@ import { createChapter, deleteChapter, getCourseChaptersMetadata, updateChapters import { useRouter } from "next/router"; import NewChapterModal from "../../../../../../components/modals/CourseEdit/NewChapter"; import NewElementModal from "../../../../../../components/modals/CourseEdit/NewElement"; -import { createElement } from "../../../../../../services/courses/elements"; +import { createElement, createFileElement } from "../../../../../../services/courses/elements"; function CourseEdit() { const router = useRouter(); @@ -79,6 +79,15 @@ function CourseEdit() { setNewElementModal(false); }; + // Submit File Upload + const submitFileElement = async (file: any, type: any, element: any, chapterId: string) => { + console.log("submitFileElement", file); + await updateChaptersMetadata(courseid, data); + await createFileElement(file, type, element, chapterId); + await getCourseChapters(); + setNewElementModal(false); + }; + const deleteChapterUI = async (chapterId: any) => { console.log("deleteChapter", chapterId); await deleteChapter(chapterId); @@ -87,7 +96,7 @@ function CourseEdit() { const updateChapters = () => { console.log(data); - updateChaptersMetadata(courseid,data); + updateChaptersMetadata(courseid, data); }; /* @@ -234,7 +243,14 @@ function CourseEdit() { {newChapterModal && } - {newElementModal && } + {newElementModal && ( + + )}
{winReady && ( diff --git a/front/services/courses/elements.ts b/front/services/courses/elements.ts index e0228b20..cf4b2777 100644 --- a/front/services/courses/elements.ts +++ b/front/services/courses/elements.ts @@ -1,59 +1,100 @@ import { getAPIUrl } from "../config"; export async function createElement(data: any, chapter_id: any) { - data.content = {} - console.log("data", data, chapter_id); + data.content = {}; + console.log("data", data, chapter_id); - // remove chapter_id from data - delete data.chapterId; - - const HeadersConfig = new Headers({ "Content-Type": "application/json" }); + // remove chapter_id from data + delete data.chapterId; + + const HeadersConfig = new Headers({ "Content-Type": "application/json" }); + + const requestOptions: any = { + method: "POST", + headers: HeadersConfig, + redirect: "follow", + credentials: "include", + body: JSON.stringify(data), + }; + + const result: any = await fetch(`${getAPIUrl()}elements/?coursechapter_id=${chapter_id}`, requestOptions) + .then((result) => result.json()) + .catch((error) => console.log("error", error)); + + console.log("result", result); + + return result; +} + +export async function createFileElement(file: File, type: string, data: any, chapter_id: any) { - const requestOptions: any = { - method: "POST", - headers: HeadersConfig, - redirect: "follow", - credentials: "include", - body: JSON.stringify(data), - }; + + const HeadersConfig = new Headers(); + + // Send file thumbnail as form data + const formData = new FormData(); + formData.append("coursechapter_id", chapter_id); + console.log("type" , type); - const result: any = await fetch(`${getAPIUrl()}elements/?coursechapter_id=${chapter_id}`, requestOptions) - .then((result) => result.json()) - .catch((error) => console.log("error", error)); - - console.log("result", result); - - return result; + + let endpoint = `${getAPIUrl()}elements/video`; + + if (type === "video") { + formData.append("name", data.name); + formData.append("video_file", file); + endpoint = `${getAPIUrl()}elements/video`; } - export async function getElement(element_id: any) { - const requestOptions: any = { - method: "GET", - redirect: "follow", - credentials: "include", - }; + console.log(); - const result: any = await fetch(`${getAPIUrl()}elements/${element_id}`, requestOptions) - .then((result) => result.json()) - .catch((error) => console.log("error", error)); - - return result; - } - export async function updateElement(data: any, element_id: any) { - const HeadersConfig = new Headers({ "Content-Type": "application/json" }); + const requestOptions: any = { + method: "POST", + headers: HeadersConfig, + redirect: "follow", + credentials: "include", + body: formData, + }; + + const result: any = await fetch(endpoint, requestOptions) + .then((result) => result.json()) + .catch((error) => console.log("error", error)); + - const requestOptions: any = { - method: "PUT", - headers: HeadersConfig, - redirect: "follow", - credentials: "include", - body: JSON.stringify(data), - }; - const result: any = await fetch(`${getAPIUrl()}elements/${element_id}`, requestOptions) - .then((result) => result.json()) - .catch((error) => console.log("error", error)); - - return result; - } \ No newline at end of file + console.log("result", result); + + return result; +} + +export async function getElement(element_id: any) { + const requestOptions: any = { + method: "GET", + redirect: "follow", + credentials: "include", + }; + + const result: any = await fetch(`${getAPIUrl()}elements/${element_id}`, requestOptions) + .then((result) => result.json()) + .catch((error) => console.log("error", error)); + + return result; +} + +export async function updateElement(data: any, element_id: any) { + const HeadersConfig = new Headers({ "Content-Type": "application/json" }); + + const requestOptions: any = { + method: "PUT", + headers: HeadersConfig, + redirect: "follow", + credentials: "include", + body: JSON.stringify(data), + }; + + const result: any = await fetch(`${getAPIUrl()}elements/${element_id}`, requestOptions) + .then((result) => result.json()) + .catch((error) => console.log("error", error)); + + return result; +}