mirror of
https://github.com/samkaraca/lazuri-doviguram.git
synced 2026-04-29 17:59:51 +00:00
landing and theme page for admin made client side rendered
This commit is contained in:
parent
56d49d10aa
commit
d5ed9201c5
@ -12,7 +12,6 @@ export function YouTubeVideoUrlTester({
|
||||
media: OptionalStringValueProperty;
|
||||
setMedia: Dispatch<SetStateAction<OptionalStringValueProperty>>;
|
||||
}) {
|
||||
console.log(media);
|
||||
return (
|
||||
<div>
|
||||
{media.status !== "success" && (
|
||||
|
||||
@ -3,9 +3,11 @@ import { LessonSideBar } from "./lesson_side_bar";
|
||||
import { ThemeSideBar } from "./theme_side_bar";
|
||||
import { InteractiveFeedbacks } from "@/core/components/interactive_feedbacks";
|
||||
import { useAdminViewModelContext } from "../theme_page/view_model/context_providers/admin_view_model";
|
||||
import { useBaseViewModelContext } from "../theme_page/view_model/context_providers/base_view_model";
|
||||
|
||||
export function AdminTools() {
|
||||
const { stalling, snackbar, setSnackbar } = useAdminViewModelContext()!;
|
||||
const { activeLesson } = useBaseViewModelContext()!;
|
||||
const [isThemeSideBarOpen, setIsThemeSideBarOpen] = useState(false);
|
||||
const [isLessonSideBarOpen, setIsLessonSideBarOpen] = useState(false);
|
||||
|
||||
@ -16,11 +18,14 @@ export function AdminTools() {
|
||||
isOpen={isThemeSideBarOpen}
|
||||
setIsOpen={setIsThemeSideBarOpen}
|
||||
/>
|
||||
<LessonSideBar
|
||||
hide={isThemeSideBarOpen}
|
||||
isOpen={isLessonSideBarOpen}
|
||||
setIsOpen={setIsLessonSideBarOpen}
|
||||
/>
|
||||
{activeLesson !== null && (
|
||||
<LessonSideBar
|
||||
hide={isThemeSideBarOpen}
|
||||
isOpen={isLessonSideBarOpen}
|
||||
setIsOpen={setIsLessonSideBarOpen}
|
||||
activeLesson={activeLesson}
|
||||
/>
|
||||
)}
|
||||
<InteractiveFeedbacks
|
||||
stalling={stalling}
|
||||
snackbar={snackbar}
|
||||
|
||||
@ -15,17 +15,19 @@ export function LessonSideBar({
|
||||
isOpen,
|
||||
setIsOpen,
|
||||
hide,
|
||||
activeLesson,
|
||||
}: {
|
||||
isOpen: boolean;
|
||||
setIsOpen: Dispatch<SetStateAction<boolean>>;
|
||||
hide: boolean;
|
||||
activeLesson: number;
|
||||
}) {
|
||||
const pathname = usePathname();
|
||||
const { push } = useRouter();
|
||||
const [modified, setModified] = useState(false);
|
||||
const [adminLessonTitle, setAdminLessonTitle] = useState("");
|
||||
const [adminLessonExplanation, setAdminLessonExplanation] = useState("");
|
||||
const { activeLesson, lessons } = useBaseViewModelContext()!;
|
||||
const { lessons } = useBaseViewModelContext()!;
|
||||
const {
|
||||
saveLesson,
|
||||
createNewLesson,
|
||||
|
||||
@ -10,7 +10,7 @@ export function ThemeCard({ themeMeta }: { themeMeta: ThemeMetaDTO }) {
|
||||
return (
|
||||
<li>
|
||||
<a
|
||||
href={`${pathname}/temalar/${id}`}
|
||||
href={`/${pathname}/temalar/${id}`}
|
||||
className={`${styles["card"]} card-button`}
|
||||
>
|
||||
<img
|
||||
|
||||
@ -18,6 +18,18 @@ export function ThemesSection({
|
||||
{themeMetas.map((themeMeta) => {
|
||||
return <ThemeCard key={themeMeta.id} themeMeta={themeMeta} />;
|
||||
})}
|
||||
{/* <button
|
||||
style={{
|
||||
backgroundColor: "#eee",
|
||||
border: "1px solid #ccc",
|
||||
display: "flex",
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
fontSize: "1.5rem",
|
||||
}}
|
||||
>
|
||||
Yeni Tema +
|
||||
</button> */}
|
||||
</ol>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
@ -18,7 +18,7 @@ export interface BaseViewModel {
|
||||
setThemeYoutubeVideoUrl: Dispatch<
|
||||
SetStateAction<BaseViewModel["themeYoutubeVideoUrl"]>
|
||||
>;
|
||||
activeLesson: number;
|
||||
activeLesson: number | null;
|
||||
setActiveLesson: Dispatch<SetStateAction<BaseViewModel["activeLesson"]>>;
|
||||
isActivityDialogOpen: boolean;
|
||||
openActivity: (activity: Activity<any>) => void;
|
||||
|
||||
@ -3,9 +3,11 @@ import { useBaseViewModelContext } from "../../view_model/context_providers/base
|
||||
import { BaseViewModel } from "../../model/base_view_model";
|
||||
|
||||
export function TabBar() {
|
||||
const { lessons, activeLesson, setActiveLesson, isAdmin } =
|
||||
const { lessons, activeLesson, setActiveLesson } =
|
||||
useBaseViewModelContext() as BaseViewModel;
|
||||
|
||||
if (!activeLesson) return null;
|
||||
|
||||
return (
|
||||
<Tabs
|
||||
value={activeLesson}
|
||||
|
||||
@ -1,10 +1,8 @@
|
||||
import { useBaseViewModelContext } from "./context_providers/base_view_model";
|
||||
import { AdminViewModel } from "../model/admin_view_model";
|
||||
import { LessonRepository } from "@/core/models/repositories/lesson_repository";
|
||||
import { useState } from "react";
|
||||
import { StatusResponse } from "@/core/models/repositories/status_response";
|
||||
import { Activity, LessonMap } from "@/core/models/entities/learning_unit";
|
||||
import { usePathname, useRouter } from "next/navigation";
|
||||
|
||||
export function useAdminViewModel(): AdminViewModel {
|
||||
const {
|
||||
@ -93,6 +91,7 @@ export function useAdminViewModel(): AdminViewModel {
|
||||
title: string;
|
||||
explanation: string;
|
||||
}) => {
|
||||
if (!activeLesson) return;
|
||||
setStalling(true);
|
||||
const lessonId = lessons.meta[activeLesson].id;
|
||||
const resObj = await fetch(`/api/admin/temalar/${themeId}/${lessonId}`, {
|
||||
@ -169,6 +168,7 @@ export function useAdminViewModel(): AdminViewModel {
|
||||
};
|
||||
|
||||
const deleteLesson = async () => {
|
||||
if (!activeLesson) return;
|
||||
setStalling(true);
|
||||
const lessonId = lessons.meta[activeLesson].id;
|
||||
const resObj = await fetch(`/api/admin/temalar/${themeId}/${lessonId}`, {
|
||||
@ -205,10 +205,11 @@ export function useAdminViewModel(): AdminViewModel {
|
||||
);
|
||||
return newLessons;
|
||||
});
|
||||
setActiveLesson((prev) => (prev === 0 ? prev : prev - 1));
|
||||
setActiveLesson((prev) => (prev ? (prev === 0 ? null : prev - 1) : null));
|
||||
};
|
||||
|
||||
const createNewActivity = async () => {
|
||||
if (!activeLesson) return;
|
||||
setStalling(true);
|
||||
const lessonId = lessons.meta[activeLesson].id;
|
||||
const resObj = await fetch(`/api/admin/temalar/${themeId}/${lessonId}`, {
|
||||
@ -260,6 +261,7 @@ export function useAdminViewModel(): AdminViewModel {
|
||||
activityIndex: number;
|
||||
activityId: string;
|
||||
}) => {
|
||||
if (!activeLesson) return;
|
||||
setStalling(true);
|
||||
const lessonId = lessons.meta[activeLesson].id;
|
||||
const resObj = await fetch(
|
||||
|
||||
@ -13,7 +13,9 @@ export function useBaseViewModel(
|
||||
theme.youtubeVideoUrl
|
||||
);
|
||||
const [lessons, setLessons] = useState(theme.lessons);
|
||||
const [activeLesson, setActiveLesson] = useState(0);
|
||||
const [activeLesson, setActiveLesson] = useState<number | null>(
|
||||
theme.lessons.meta.length > 0 ? 0 : null
|
||||
);
|
||||
|
||||
// ACTIVITY DIALOG
|
||||
const [activeActivity, setActiveActivity] = useState<Activity<any> | null>(
|
||||
|
||||
@ -1,13 +1,21 @@
|
||||
import { ThemeMetaDTO } from "@/core/models/dtos/theme_meta_dto";
|
||||
import { ThemeReposityImplementation } from "@/core/models/repositories/theme_repository_implementation";
|
||||
import { LandingPageView } from "@/features/landing_page_view";
|
||||
import Head from "next/head";
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
export default function AdminPage() {
|
||||
const [themeMetas, setThemeMetas] = useState<ThemeMetaDTO[]>([]);
|
||||
|
||||
const fetchThemeMetas = async () => {
|
||||
const resObj = await fetch(`/api/admin/temalar`);
|
||||
const res = (await resObj.json()) as ThemeMetaDTO[];
|
||||
setThemeMetas(res);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
fetchThemeMetas();
|
||||
}, []);
|
||||
|
||||
export default function AdminPage({
|
||||
themeMetas,
|
||||
}: {
|
||||
themeMetas: ThemeMetaDTO[];
|
||||
}) {
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
@ -18,14 +26,3 @@ export default function AdminPage({
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export async function getServerSideProps() {
|
||||
const themeRepository = new ThemeReposityImplementation();
|
||||
const themeMetas = await themeRepository.getThemeMetas();
|
||||
|
||||
return {
|
||||
props: {
|
||||
themeMetas,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@ -1,20 +1,33 @@
|
||||
import { GetServerSidePropsContext } from "next";
|
||||
import { ThemeReposityImplementation } from "@/core/models/repositories/theme_repository_implementation";
|
||||
import { Theme } from "@/core/models/entities/learning_unit";
|
||||
import { ThemePage as ThemePageElement } from "@/features/theme_page";
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
export default function ThemePage({ themeData }: { themeData: Theme }) {
|
||||
return <ThemePageElement theme={Theme.from(themeData)} isAdmin={true} />;
|
||||
export default function ThemePage({ themeId }: { themeId: string }) {
|
||||
const [themeData, setThemeData] = useState<Theme>();
|
||||
|
||||
const fetchTheme = async (themeId: string) => {
|
||||
const resObj = await fetch(`/api/admin/temalar/${themeId}`);
|
||||
const res = (await resObj.json()) as Theme;
|
||||
setThemeData(Theme.from(res));
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
fetchTheme(themeId);
|
||||
}, [themeId]);
|
||||
|
||||
if (themeData) return <ThemePageElement theme={themeData} isAdmin={true} />;
|
||||
|
||||
return (
|
||||
<div className="admin-waiting-room">
|
||||
<h1>Merhaba Admin!</h1>
|
||||
<p>Tema Yükleniyor...</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export async function getServerSideProps(context: GetServerSidePropsContext) {
|
||||
const path = context.params as unknown as { theme: string };
|
||||
const themeRepository = new ThemeReposityImplementation();
|
||||
const themeData = await themeRepository.getThemeData(path.theme);
|
||||
const { theme } = context.params as unknown as { theme: string };
|
||||
|
||||
return {
|
||||
props: {
|
||||
themeData,
|
||||
},
|
||||
};
|
||||
return { props: { themeId: theme } };
|
||||
}
|
||||
|
||||
@ -27,6 +27,10 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
}
|
||||
|
||||
return res.status(501).json({ error: "Unsopported action" });
|
||||
} else if (req.method === "GET") {
|
||||
const theme = req.query.theme as string;
|
||||
const themeData = await themeRepo.getThemeData(theme);
|
||||
return res.status(200).json(themeData);
|
||||
}
|
||||
|
||||
return res.status(501).json({ error: "Unsopported request method" });
|
||||
|
||||
@ -1,7 +1,10 @@
|
||||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
import { ThemeReposityImplementation } from "@/core/models/repositories/theme_repository_implementation";
|
||||
|
||||
async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
export default async function handler(
|
||||
req: NextApiRequest,
|
||||
res: NextApiResponse
|
||||
) {
|
||||
const themeRepo = new ThemeReposityImplementation();
|
||||
|
||||
if (req.method === "PUT") {
|
||||
@ -18,9 +21,10 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
}
|
||||
|
||||
return res.status(501).json({ error: "Unsopported action" });
|
||||
} else if (req.method === "GET") {
|
||||
const themeMetas = await themeRepo.getThemeMetas();
|
||||
return res.status(200).json(themeMetas);
|
||||
}
|
||||
|
||||
return res.status(501).json({ error: "Unsopported request method" });
|
||||
}
|
||||
|
||||
export default handler;
|
||||
|
||||
@ -80,6 +80,18 @@ div.simple-card {
|
||||
}
|
||||
}
|
||||
|
||||
div.admin-waiting-room {
|
||||
height: 100vh;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
row-gap: 3rem;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
font-size: 120%;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
@media (max-width: 400px) {
|
||||
html {
|
||||
font-size: 75%; /* this is the base font size for screens smaller than 400px */
|
||||
|
||||
Loading…
Reference in New Issue
Block a user