fix: collections and courses remaining bugs

This commit is contained in:
swve 2024-02-04 21:02:07 +01:00
parent 4245e61df8
commit 212c50768f
8 changed files with 155 additions and 113 deletions

View file

@ -1,29 +1,27 @@
"use client";
import { useRouter } from "next/navigation";
import React from "react";
import React, { useState } from "react";
import { createCollection } from "@services/courses/collections";
import useSWR from "swr";
import { getAPIUrl, getUriWithOrg } from "@services/config/config";
import { revalidateTags, swrFetcher } from "@services/utils/ts/requests";
import { getOrganizationContextInfo } from "@services/organizations/orgs";
import { useOrg } from "@components/Contexts/OrgContext";
function NewCollection(params: any) {
const org = useOrg() as any;
const orgslug = params.params.orgslug;
const [name, setName] = React.useState("");
const [org, setOrg] = React.useState({}) as any;
const [description, setDescription] = React.useState("");
const [selectedCourses, setSelectedCourses] = React.useState([]) as any;
const router = useRouter();
const { data: courses, error: error } = useSWR(`${getAPIUrl()}courses/org_slug/${orgslug}/page/1/limit/10`, swrFetcher);
const [isPublic, setIsPublic] = useState('true');
const handleVisibilityChange = (e: React.ChangeEvent<HTMLSelectElement>) => {
setIsPublic(e.target.value);
};
React.useEffect(() => {
async function getOrg() {
const org = await getOrganizationContextInfo(orgslug, { revalidate: 1800 });
setOrg(org);
}
getOrg();
}, []);
const handleNameChange = (event: React.ChangeEvent<HTMLInputElement>) => {
setName(event.target.value);
@ -35,83 +33,94 @@ function NewCollection(params: any) {
const handleSubmit = async (e: any) => {
e.preventDefault();
const collection = {
name: name,
description: description,
courses: selectedCourses,
public: true,
public: isPublic,
org_id: org.id,
};
await createCollection(collection);
await revalidateTags(["collections"], orgslug);
await revalidateTags(["collections"], org.slug);
// reload the page
router.refresh();
router.prefetch(getUriWithOrg(orgslug, "/collections"));
router.push(getUriWithOrg(orgslug, "/collections"));
// wait for 2s before reloading the page
setTimeout(() => {
router.push(getUriWithOrg(orgslug, "/collections"));
}
, 1000);
};
return (
<>
<div className="w-64 m-auto py-20">
<div className="font-bold text-lg mb-4">Add new</div>
<div className="font-bold text-lg mb-4">Add new</div>
<input
type="text"
placeholder="Name"
value={name}
onChange={handleNameChange}
className="w-full px-4 py-2 mb-4 border rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500"
/>
<input
type="text"
placeholder="Name"
value={name}
onChange={handleNameChange}
className="w-full px-4 py-2 mb-4 border rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500"
/>
{!courses ? (
<select
onChange={handleVisibilityChange}
className="w-full px-4 py-2 mb-4 border rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500"
defaultValue={isPublic}
>
<option value="false">Private Collection</option>
<option value="true">Public Collection </option>
</select>
{!courses ? (
<p className="text-gray-500">Loading...</p>
) : (
<div>
<div className="space-y-4 p-3">
<p>Courses</p>
{courses.map((course: any) => (
<div key={course.course_uuid} className="flex items-center mb-2">
<div key={course.course_uuid} className="flex items-center space-x-2">
<input
<input
type="checkbox"
id={course.id}
name={course.name}
value={course.id}
onChange={(e) => {
if (e.target.checked) {
setSelectedCourses([...selectedCourses, course.id]);
}
else {
setSelectedCourses(selectedCourses.filter((course_uuid: any) => course_uuid !== course.course_uuid));
}
}}
className="text-blue-500 rounded focus:ring-2 focus:ring-blue-500"
/>
type="checkbox"
id={course.id}
name={course.name}
value={course.id}
// id is an integer, not a string
onChange={(e) => {
if (e.target.checked) {
setSelectedCourses([...selectedCourses, course.id]);
}
else {
setSelectedCourses(selectedCourses.filter((course_uuid: any) => course_uuid !== course.course_uuid));
}
}
}
className="mr-2"
/>
<label htmlFor={course.course_uuid} className="text-sm">{course.name}</label>
<label htmlFor={course.course_uuid} className="text-sm text-gray-700">{course.name}</label>
</div>
))}
</div>
)}
<input
type="text"
placeholder="Description"
value={description}
onChange={handleDescriptionChange}
className="w-full px-4 py-2 mb-4 border rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500"
/>
<input
type="text"
placeholder="Description"
value={description}
onChange={handleDescriptionChange}
className="w-full px-4 py-2 mb-4 border rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500"
/>
<button
onClick={handleSubmit}
className="px-6 py-3 text-white bg-black rounded-lg shadow-md hover:bg-black focus:outline-none focus:ring-2 focus:ring-blue-500"
>
Submit
</button>
<button
onClick={handleSubmit}
className="px-6 py-3 text-white bg-black rounded-lg shadow-md hover:bg-black focus:outline-none focus:ring-2 focus:ring-blue-500"
>
Submit
</button>
</div>
</>

View file

@ -59,11 +59,11 @@ const CourseClient = (props: any) => {
useEffect(() => {
getLearningTags();
}
, [org]);
, [org, course]);
return (
<>
{!course ? (
{!course && !org ? (
<PageLoading></PageLoading>
) : (
<GeneralWrapperStyled>
@ -74,8 +74,8 @@ const CourseClient = (props: any) => {
</h1>
</div>
{props.course.thumbnail_image ?
<div className="inset-0 ring-1 ring-inset ring-black/10 rounded-lg shadow-xl relative w-auto h-[400px] bg-cover bg-center mb-4" style={{ backgroundImage: `url(${getCourseThumbnailMediaDirectory(org?.org_uuid, course.course_uuid, course.thumbnail_image)})` }}>
{props.course?.thumbnail_image && org ?
<div className="inset-0 ring-1 ring-inset ring-black/10 rounded-lg shadow-xl relative w-auto h-[400px] bg-cover bg-center mb-4" style={{ backgroundImage: `url(${getCourseThumbnailMediaDirectory(org?.org_uuid, course?.course_uuid, course?.thumbnail_image)})` }}>
</div>
:
<div className="inset-0 ring-1 ring-inset ring-black/10 rounded-lg shadow-xl relative w-auto h-[400px] bg-cover bg-center mb-4" style={{ backgroundImage: `url('../empty_thumbnail.png')`, backgroundSize: 'auto' }}>
@ -193,19 +193,19 @@ const CourseClient = (props: any) => {
<div className="course_metadata_right space-y-3 w-72 antialiased flex flex-col ml-10 h-fit p-3 py-5 bg-white shadow-md shadow-gray-300/25 outline outline-1 outline-neutral-200/40 rounded-lg overflow-hidden">
{user &&
<div className="flex flex-col mx-auto space-y-3 px-2 py-2 items-center">
<UserAvatar border="border-8" avatar_url={getUserAvatarMediaDirectory(course.authors[0].user_uuid,course.authors[0].avatar_image)} width={100} />
<UserAvatar border="border-8" avatar_url={getUserAvatarMediaDirectory(course.authors[0].user_uuid, course.authors[0].avatar_image)} width={100} />
<div className="-space-y-2 ">
<div className="text-[12px] text-neutral-400 font-semibold">Author</div>
<div className="text-xl font-bold text-neutral-800">
{course.authors[0].first_name && course.authors[0].last_name && (
<div className="flex space-x-2 items-center">
<p>{course.authors[0].first_name + ' ' + course.authors[0].last_name}</p><span className="text-xs bg-neutral-100 p-1 px-3 rounded-full text-neutral-400 font-semibold"> @{course.authors[0].username }</span>
</div>)}
<div className="flex space-x-2 items-center">
<p>{course.authors[0].first_name + ' ' + course.authors[0].last_name}</p><span className="text-xs bg-neutral-100 p-1 px-3 rounded-full text-neutral-400 font-semibold"> @{course.authors[0].username}</span>
</div>)}
{!course.authors[0].first_name && !course.authors[0].last_name && (
<div className="flex space-x-2 items-center">
<p>@{course.authors[0].username}</p>
</div>)}
</div>
<div className="flex space-x-2 items-center">
<p>@{course.authors[0].username}</p>
</div>)}
</div>
</div>
</div>
}
@ -226,12 +226,4 @@ const CourseClient = (props: any) => {
};
const StyledBox = (props: any) => (
<div className="p-3 pl-10 bg-white w-[100%] h-auto ring-1 ring-inset ring-gray-400/10 rounded-lg shadow-sm">
{props.children}
</div>
);
export default CourseClient;

View file

@ -17,7 +17,7 @@ export default function Error({
return (
<div>
<ErrorUI></ErrorUI>
<ErrorUI ></ErrorUI>
</div>
);
}