Skip to content

Commit

Permalink
Merge pull request #13 from johanesPao/dev
Browse files Browse the repository at this point in the history
Pengerjaan Tulisan dan TulisanCard dan markdown
  • Loading branch information
johanesPao authored May 29, 2024
2 parents 826bca8 + 7e28b30 commit 88c2180
Show file tree
Hide file tree
Showing 10 changed files with 1,980 additions and 237 deletions.
3 changes: 0 additions & 3 deletions ui/actions.secrets

This file was deleted.

2,030 changes: 1,838 additions & 192 deletions ui/package-lock.json

Large diffs are not rendered by default.

9 changes: 9 additions & 0 deletions ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,26 @@
"@tiptap/extension-link": "^2.1.11",
"@tiptap/react": "^2.1.11",
"@tiptap/starter-kit": "^2.1.11",
"@types/d3": "^7.4.3",
"@types/react-syntax-highlighter": "^15.5.13",
"babel-plugin-prismjs": "^2.1.0",
"d3": "^7.9.0",
"dayjs": "^1.11.10",
"embla-carousel-react": "^7.1.0",
"flowbite": "^2.3.0",
"flowbite-react": "^0.6.4",
"framer-motion": "^10.16.4",
"marked": "^12.0.2",
"prismjs": "^1.29.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-icons": "^4.11.0",
"react-markdown": "^9.0.1",
"react-router-dom": "^6.16.0",
"react-syntax-highlighter": "^15.5.0",
"rehype-katex": "^7.0.0",
"remark-gfm": "^4.0.0",
"remark-math": "^6.0.0",
"typewriter-effect": "^2.21.0"
},
"devDependencies": {
Expand Down
12 changes: 10 additions & 2 deletions ui/src/fungsi/tulisan.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import { ResponTulisanProps, TulisanProps } from "../props/Tulisan.props";

export const fetchTulisanDiterbitkan = async (
setDaftarTulisan: React.Dispatch<React.SetStateAction<TulisanProps[] | null>>
setDaftarTulisan: React.Dispatch<React.SetStateAction<TulisanProps[] | null>>,
setMemuat: React.Dispatch<React.SetStateAction<boolean>>
) => {
// setMemuat true
setMemuat(true);
try {
const APIEndpoint = import.meta.env.DEV ? import.meta.env.VITE_DEV_API : import.meta.env.VITE_PROD_API;
const APIUrl = `${APIEndpoint}/tulisan/diterbitkan`
Expand Down Expand Up @@ -36,12 +39,16 @@ export const fetchTulisanDiterbitkan = async (
} catch (kesalahan) {
console.error(kesalahan);
}
// setMemuat false
setMemuat(false);
};

export const fetchTulisan = async (
id: string,
setTulisan: React.Dispatch<React.SetStateAction<TulisanProps | null>>
setTulisan: React.Dispatch<React.SetStateAction<TulisanProps | null>>,
setMemuat: React.Dispatch<React.SetStateAction<boolean>>
) => {
setMemuat(true);
try {
const APIEndpoint = import.meta.env.DEV ? import.meta.env.VITE_DEV_API : import.meta.env.VITE_PROD_API;
const APIUrl = `${APIEndpoint}/tulisan/${id}`
Expand Down Expand Up @@ -72,4 +79,5 @@ export const fetchTulisan = async (
} catch (kesalahan) {
console.log(kesalahan);
}
setMemuat(false);
};
4 changes: 2 additions & 2 deletions ui/src/halaman/Landing.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ const Landing = () => {
return (
<>
<div className="flex flex-col xl:flex-row bg-stone-900 min-h-screen py-0 px-0">
<div className="fixed xl:w-96">
<div className="fixed xl:w-96 z-50">
<HeaderLanding/>
</div>
<div className="xl:pl-96 pt-44 xl:pt-0 xl:grow">
<div className="xl:pl-96 pt-44 xl:pt-0 xl:w-screen bg-stone-900">
<BodyLanding/>
</div>
</div>
Expand Down
31 changes: 23 additions & 8 deletions ui/src/komponen/DaftarTulisan.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,36 @@ import { useEffect, useState } from "react";
import { TulisanProps } from "../props/Tulisan.props";
import TulisanCard from "./TulisanCard";
import { fetchTulisanDiterbitkan } from "../fungsi/tulisan";
import SkeletonTulisan from "./SkeletonTulisan";

const DaftarTulisan = () => {
const [daftarTulisan, setDaftarTulisan] = useState<TulisanProps[] | null>(null)
const [daftarTulisan, setDaftarTulisan] = useState<TulisanProps[] | null>(null);
const [memuat, setMemuat] = useState<boolean>(false);

useEffect(() => {
fetchTulisanDiterbitkan(setDaftarTulisan);
fetchTulisanDiterbitkan(setDaftarTulisan, setMemuat);
}, [])

return (
<div>
{daftarTulisan !== null && daftarTulisan.map(tulisan => {
return (
<TulisanCard key={tulisan.id} data={tulisan} />
)
})}
<div className="w-full flex flex-col gap-12">
{
memuat ? (
<div className="flex flex-col gap-12">
<SkeletonTulisan />
<SkeletonTulisan />
<SkeletonTulisan />
<SkeletonTulisan />
<SkeletonTulisan />
</div>
) :
daftarTulisan !== null && daftarTulisan.map(tulisan => {
return (
<div>
<TulisanCard key={tulisan.id} data={tulisan} />
</div>
)
})
}
</div>
)
}
Expand Down
21 changes: 21 additions & 0 deletions ui/src/komponen/SkeletonTulisan.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
const SkeletonTulisan = () => {
return (
<div className="w-full p-2 first:pt-0 last:pb-0">
<div className="flex flex-col animate-pulse gap-2">
<div className="rounded-sm bg-emerald-950 h-8 max-w-[300px]"></div>
<div className="rounded-sm bg-stone-800 h-3 max-w-[240px]"></div>
<div className="rounded-sm bg-zinc-800 h-3 max-w-[180px]"></div>
<div className="rounded-sm bg-zinc-800 h-3 max-w-[160px]"></div>
<div className="rounded-sm bg-zinc-800 h-3 max-w-[190px]"></div>
<div className="rounded-sm bg-zinc-700 h-4 max-w-[70rem]"></div>
<div className="rounded-sm bg-zinc-700 h-4 max-w-[72rem]"></div>
<div className="rounded-sm bg-zinc-700 h-4 max-w-[68rem]"></div>
<div className="rounded-sm bg-zinc-700 h-4 max-w-[70rem]"></div>
<div className="rounded-sm bg-zinc-700 h-4 max-w-[71rem]"></div>
<div className="rounded-sm bg-zinc-700 h-4 max-w-[66rem]"></div>
</div>
</div>
)
}

export default SkeletonTulisan;
60 changes: 40 additions & 20 deletions ui/src/komponen/Tulisan.tsx
Original file line number Diff line number Diff line change
@@ -1,40 +1,60 @@
import { useParams } from "react-router-dom";
import Markdown from 'react-markdown';
import remarkGfm from "remark-gfm";
import remarkMath from "remark-math";
import rehypeKatex from "rehype-katex";
import 'katex/dist/katex.min.css';
import { TulisanProps } from "../props/Tulisan.props";
import { useEffect, useState } from "react";
import { fetchTulisan } from "../fungsi/tulisan";
import { opsiStringDate } from "../interface";
import KategoriCard from "./KategoriCard";
import SkeletonTulisan from "./SkeletonTulisan";

const Tulisan = () => {
const { idTulisan } = useParams();

const [tulisan, setTulisan] = useState<TulisanProps | null>(null)
const [tulisan, setTulisan] = useState<TulisanProps | null>(null);
const [memuat, setMemuat] = useState<boolean>(false);

useEffect(() => {
if (idTulisan !== undefined) {
fetchTulisan(idTulisan, setTulisan);
fetchTulisan(idTulisan, setTulisan, setMemuat);
}
}, [])

return tulisan ?
(
<div className="flex flex-col px-2 gap-1">
<div className="text-2xl font-sans font-semibold subpixel-antialiased text-emerald-400">
{tulisan.judul}
return (
<>
{memuat ? (
<SkeletonTulisan />
) : tulisan ?
(
<div className="flex flex-col px-2 gap-1">
<div className="text-2xl font-sans font-semibold subpixel-antialiased text-emerald-400">
{tulisan.judul}
</div>
<div className="text-stone-400 text-sm italic">
{tulisan.dibuat.toLocaleDateString('en-ID', opsiStringDate)}
</div>
<div>
{tulisan.kategori?.map(itemKategori => (
<KategoriCard props={itemKategori} />
))}
</div>
<div className="xl:text-base text-sm break-words hyphens-auto indent-8 text-justify">
{tulisan.konten ? (
<Markdown
remarkPlugins={[remarkGfm, remarkMath]}
rehypePlugins={[rehypeKatex]}
>
{tulisan.konten}
</Markdown>
) : null}
</div>
</div>
<div className="text-stone-400 text-sm italic">
{tulisan.dibuat.toLocaleDateString('en-ID', opsiStringDate)}
</div>
<div>
{tulisan.kategori?.map(itemKategori => (
<KategoriCard props={itemKategori} />
))}
</div>
<div className="xl:text-base text-xs">
{tulisan.konten}
</div>
</div>
) : null
) : null}
</>
)
}

export default Tulisan;
40 changes: 35 additions & 5 deletions ui/src/komponen/TulisanCard.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,20 @@
import { useNavigate } from "react-router-dom";
import Markdown from 'react-markdown';
import remarkGfm from 'remark-gfm';
import remarkMath from 'remark-math';
import rehypeKatex from 'rehype-katex';
import 'katex/dist/katex.min.css';
import { TulisanProps } from "../props/Tulisan.props";
import { opsiStringDate } from "../interface";
import KategoriCard from "./KategoriCard";


const TulisanCard = ({data}: {data: TulisanProps}) => {
const navigasi = useNavigate();

// const komponen = {
// TestChart
// }

const lihatTulisan = (id: string) => {
return navigasi(`tulisan/${id}`)
}
Expand All @@ -26,12 +34,34 @@ const TulisanCard = ({data}: {data: TulisanProps}) => {
{data.dibuat.toLocaleDateString('en-ID', opsiStringDate)}
</div>
<div>
{data.kategori?.map(itemKategori => (
<KategoriCard props={itemKategori} />
{data.kategori?.map((itemKategori, indeks) => (
<KategoriCard key={indeks} props={itemKategori} />
))}
</div>
<div className="xl:text-base text-xs">
{data.konten}
{/* <div className="xl:text-base text-xs">
{data.konten ? (
<Markdown
options={{
wrapper: 'article',
forceWrapper: true,
overrides: {
TestChart,
KonversiLatex
}
}}
>
{data.konten}
</Markdown>
): null}
</div> */}
<div className="flex flex-col xl:text-base text-sm break-words hyphens-auto line-clamp-6 text-justify">
<Markdown
remarkPlugins={[remarkGfm, remarkMath]}
rehypePlugins={[rehypeKatex]}
className="line-clamp-6"
>
{data.konten}
</Markdown>
</div>
</div>
</>
Expand Down
7 changes: 2 additions & 5 deletions ui/src/rute.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
import { Suspense, lazy } from "react";
import LayarMemuat from "./komponen/LayarMemuat";
import type { RouteObject } from "react-router";
// import Tulisan from "./komponen/Tulisan";
// import DaftarTulisan from "./komponen/DaftarTulisan";
import Tulisan from "./komponen/Tulisan";
import DaftarTulisan from "./komponen/DaftarTulisan";

// eslint-disable-next-line @typescript-eslint/no-explicit-any
const Loadable = (Component: any) => (props: JSX.IntrinsicAttributes) =>
Expand All @@ -16,9 +16,6 @@ const Loadable = (Component: any) => (props: JSX.IntrinsicAttributes) =>
// * LANDING
const Landing = Loadable(lazy(() => import("./halaman/Landing")));
const CV = Loadable(lazy(() => import("./halaman/CV")));
// * TULISAN
const DaftarTulisan = Loadable(lazy(() => import("./komponen/DaftarTulisan")));
const Tulisan = Loadable(lazy(() => import("./komponen/Tulisan")));

const rute: RouteObject[] = [
{
Expand Down

0 comments on commit 88c2180

Please sign in to comment.