list pages from pocketbase
This commit is contained in:
parent
699fbf06c5
commit
23d6930bd6
|
|
@ -1,5 +1,6 @@
|
|||
import { memo, useEffect, useRef } from "react";
|
||||
import EditorJS, { OutputData } from "@editorjs/editorjs";
|
||||
import EditorJS from "@editorjs/editorjs";
|
||||
import type { OutputData } from "@editorjs/editorjs";
|
||||
import { EDITOR_JS_TOOLS } from "@/utils/tools";
|
||||
|
||||
type Props = {
|
||||
|
|
@ -17,7 +18,7 @@ const EditorBlock = ({ data, onChange, holder }: Props) => {
|
|||
holder: holder,
|
||||
tools: EDITOR_JS_TOOLS,
|
||||
data,
|
||||
async onChange(api, event) {
|
||||
async onChange(api) {
|
||||
const data = await api.saver.save();
|
||||
onChange(data);
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,27 +0,0 @@
|
|||
import type { PagesRecord } from '@/@types/pocketbase-types';
|
||||
import Layout from '@/layouts/Home'
|
||||
import { getPageBySlug } from '@/utils/pb'
|
||||
|
||||
export default function Page({data}: {slug: string, data: PagesRecord}) {
|
||||
return (
|
||||
<Layout title={data.title}>
|
||||
<h1>{data.title}</h1>
|
||||
<pre>{JSON.stringify(data.content, null, 2)}</pre>
|
||||
</Layout>
|
||||
)
|
||||
}
|
||||
|
||||
export async function getServerSideProps({params}: {params: {slug: string}}) {
|
||||
const {data, error} = await getPageBySlug(params.slug);
|
||||
if (error || !data) {
|
||||
return {
|
||||
notFound: true,
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
props: {
|
||||
data: data,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,101 @@
|
|||
import type { PagesRecord } from '@/@types/pocketbase-types';
|
||||
import Layout from '@/layouts/Home'
|
||||
import { getPageBySlug } from '@/utils/pb'
|
||||
|
||||
function parseBoldText(text: string) {
|
||||
const parts = text.split(/(<b>.*?<\/b>)/g);
|
||||
const result = [];
|
||||
for (let i = 0; i < parts.length; i++) {
|
||||
if (parts[i]?.startsWith('<b>')) {
|
||||
result.push(<b key={i}>{parts[i]?.slice(3, -4)}</b>)
|
||||
} else {
|
||||
result.push(parts[i])
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function Paragraph({text}: {text: string}) {
|
||||
return <p className='text-xl'>{parseBoldText(text)}</p>
|
||||
}
|
||||
|
||||
function Heading({text, level}: {text: string, level: number}) {
|
||||
switch (level) {
|
||||
case 1:
|
||||
return (
|
||||
<>
|
||||
<h1 className='font-poppins text-5xl'>{text}</h1>
|
||||
<div className="line h-1 w-full bg-black"></div>
|
||||
</>
|
||||
)
|
||||
case 2:
|
||||
return <h2 className='text-2xl'>{text}</h2>
|
||||
case 3:
|
||||
return <h3>{text}</h3>
|
||||
default:
|
||||
return <h4>{text}</h4>
|
||||
}
|
||||
}
|
||||
|
||||
type ParagraphBlock = {
|
||||
type: 'paragraph',
|
||||
data: {
|
||||
text: string,
|
||||
},
|
||||
id: string,
|
||||
}
|
||||
|
||||
type HeaderBlock = {
|
||||
type: 'header',
|
||||
data: {
|
||||
text: string,
|
||||
level: number,
|
||||
},
|
||||
id: string,
|
||||
}
|
||||
|
||||
type Block = ParagraphBlock | HeaderBlock;
|
||||
|
||||
type Content = {
|
||||
blocks: Block[],
|
||||
version: string,
|
||||
time: number,
|
||||
}
|
||||
|
||||
export default function Page({data}: {slug: string, data: PagesRecord<Content>}) {
|
||||
return (
|
||||
<Layout title={data.title}>
|
||||
<div className="container mx-auto p-8">
|
||||
<p>Here is the content rendered:</p>
|
||||
<div className="flex flex-col gap-6">
|
||||
{data.content && data.content.blocks.map((block, index): (JSX.Element | null) => {
|
||||
switch (block.type) {
|
||||
case 'paragraph':
|
||||
return <Paragraph key={index} text={block.data.text} />
|
||||
case 'header':
|
||||
return <Heading key={index} text={block.data.text} level={block.data.level} />
|
||||
default:
|
||||
return <p key={index}>Unknown block type: <pre>{JSON.stringify(block, null, 2)}</pre></p>
|
||||
}
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
<pre>{JSON.stringify(data.content, null, 2)}</pre>
|
||||
</Layout>
|
||||
)
|
||||
}
|
||||
|
||||
export async function getServerSideProps({params}: {params: {slug: string}}) {
|
||||
const {data, error} = await getPageBySlug(params.slug);
|
||||
if (error || !data) {
|
||||
return {
|
||||
notFound: true,
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
props: {
|
||||
data: data,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
@ -2,6 +2,7 @@ import dynamic from 'next/dynamic'
|
|||
import Layout from '@/layouts/Home'
|
||||
import { useState } from 'react'
|
||||
import { OutputData } from "@editorjs/editorjs";
|
||||
import { api } from '@/utils/api';
|
||||
|
||||
const ReactEditorJS = dynamic(() => import('@/components/ReactEditor'), {
|
||||
ssr: false
|
||||
|
|
@ -9,8 +10,26 @@ const ReactEditorJS = dynamic(() => import('@/components/ReactEditor'), {
|
|||
|
||||
export default function Editor() {
|
||||
const [data, setData] = useState<OutputData>()
|
||||
const {mutate, isLoading, data: data2, isError} = api.pages.updatePage.useMutation();
|
||||
|
||||
if (data2) console.log(data2)
|
||||
|
||||
const handleSubmit = () => {
|
||||
if (!data) return
|
||||
mutate({
|
||||
slug: 'test',
|
||||
title: 'Test',
|
||||
content: data
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
<Layout title='React EditorJS'>
|
||||
<Layout title='EditorJS'>
|
||||
<button onClick={handleSubmit}>Save</button>
|
||||
{isLoading && <p>Loading...</p>}
|
||||
{data2 && !isError && <p>Saved!</p>}
|
||||
{isError && <p>Error!</p>}
|
||||
|
||||
<h1>React EditorJS</h1>
|
||||
<div className="container mx-auto p-8">
|
||||
<h2>EditorJS with React</h2>
|
||||
|
|
@ -1,13 +1,13 @@
|
|||
import { z } from "zod";
|
||||
import { createTRPCRouter, publicProcedure } from "../trpc";
|
||||
import { getPage, getPages } from "@/utils/pb";
|
||||
import { getPageById, getPages, updatePage, getIdFromSlug } from "@/utils/pb";
|
||||
|
||||
export const pagesRouter = createTRPCRouter({
|
||||
getPage: publicProcedure
|
||||
.input(z.object({ id: z.string() }))
|
||||
.query(({ input }) => {
|
||||
return {
|
||||
data: getPage(input.id),
|
||||
data: getPageById(input.id),
|
||||
};
|
||||
}),
|
||||
getPages: publicProcedure
|
||||
|
|
@ -16,4 +16,28 @@ export const pagesRouter = createTRPCRouter({
|
|||
data: getPages(),
|
||||
};
|
||||
}),
|
||||
updatePage: publicProcedure
|
||||
.input(z.object({ slug: z.string(), title: z.string().optional(), content: z.any().optional() }))
|
||||
.mutation(async ({ input }) => {
|
||||
const id = await getIdFromSlug(input.slug);
|
||||
if (!id || id.error || !id.data) {
|
||||
return {
|
||||
error: {
|
||||
code: "NOT_FOUND",
|
||||
message: "Page not found",
|
||||
},
|
||||
};
|
||||
}
|
||||
let data = {};
|
||||
if (input.title) {
|
||||
data = { ...data, title: input.title };
|
||||
}
|
||||
if (input.content) {
|
||||
data = { ...data, content: input.content };
|
||||
}
|
||||
const res = await updatePage(id.data, data);
|
||||
return {
|
||||
data: res,
|
||||
};
|
||||
}),
|
||||
});
|
||||
|
|
|
|||
|
|
@ -56,4 +56,16 @@ async function updatePage(id: string, data: PagesRecord) {
|
|||
}
|
||||
}
|
||||
|
||||
export { pb, getPages, getPageById, getPageBySlug, createPage, updatePage };
|
||||
async function getIdFromSlug(slug: string) {
|
||||
try {
|
||||
const res = await pb
|
||||
.collection("pages")
|
||||
.getFirstListItem('slug="' + slug + '"');
|
||||
return { data: res.id };
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
return { error };
|
||||
}
|
||||
}
|
||||
|
||||
export { pb, getPages, getPageById, getPageBySlug, createPage, updatePage, getIdFromSlug };
|
||||
|
|
|
|||
Loading…
Reference in New Issue