feat: payload setup for user, media, blog

This commit is contained in:
RizqiSyahrendra 2025-02-03 03:19:32 +07:00
parent d88cff95d6
commit 3b25223659
26 changed files with 8068 additions and 82 deletions

8
.env.example Normal file
View File

@ -0,0 +1,8 @@
# Added by Payload
DATABASE_URI=your-connection-string-here
PAYLOAD_SECRET=YOUR_SECRET_HERE
S3_BUCKET=YOUR_BUCKET
S3_ACCESS_KEY_ID=YOUR_ACCESS_KEY
S3_SECRET_ACCESS_KEY=YOUR_SECRET
S3_REGION=YOUR_REGION
S3_ENDPOINT=YOUR_ENDPOINT

1
.gitignore vendored
View File

@ -32,6 +32,7 @@ yarn-error.log*
# env files (can opt-in for committing if needed)
.env*
!.env.example
# vercel
.vercel

View File

@ -1,7 +1,22 @@
import { withPayload } from "@payloadcms/next/withPayload";
import type { NextConfig } from "next";
const nextConfig: NextConfig = {
/* config options here */
// webpack: (config, options) => {
// config.module.rules.push({
// test: require.resolve("wowjs/dist/wow.js"),
// use: [
// {
// loader: "exports-loader",
// options: {
// exports: "this.WOW",
// },
// },
// ],
// });
// return config;
// },
};
export default nextConfig;
export default withPayload(nextConfig);

7034
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -2,28 +2,41 @@
"name": "my-app",
"version": "0.1.0",
"private": true,
"type": "module",
"scripts": {
"dev": "next dev --turbopack",
"dev-old": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint"
"lint": "next lint",
"payload:generate:types": "payload generate:types",
"tsc": "tsc"
},
"dependencies": {
"@payloadcms/db-postgres": "^3.20.0",
"@payloadcms/next": "^3.20.0",
"@payloadcms/payload-cloud": "^3.20.0",
"@payloadcms/richtext-lexical": "^3.20.0",
"@payloadcms/storage-s3": "^3.20.0",
"@popperjs/core": "2.11.8",
"bootstrap": "^5.1.3",
"graphql": "^16.10.0",
"imagesloaded": "^5.0.0",
"isotope-layout": "^3.0.6",
"jarallax": "^2.2.1",
"next": "15.1.6",
"payload": "^3.20.0",
"photoswipe": "^5.4.4",
"react": "^19.0.0",
"react-dom": "^19.0.0",
"react-modal-video": "^2.0.2",
"react-photoswipe-gallery": "^3.0.1",
"rellax": "^1.12.1",
"sharp": "^0.33.5",
"swiper": "^11.1.4",
"tippy.js": "^6.3.7",
"typewriter-effect": "^2.21.0",
"wow.js": "^1.2.2",
"wowjs": "^1.1.3"
},
"devDependencies": {
@ -39,6 +52,7 @@
"eslint-config-next": "15.1.6",
"eslint-config-prettier": "^10.0.1",
"eslint-plugin-prettier": "^5.2.3",
"exports-loader": "^5.0.0",
"postcss": "^8",
"prettier": "^3.4.2",
"tailwindcss": "^3.4.1",

View File

@ -0,0 +1,217 @@
import BlogComments from "@/components/BlogComments";
import BlogWidget from "@/components/BlogWidget";
import CommentForm from "@/components/CommentForm";
import { allBlogs } from "@/data/blogs";
import payloadConfig from "@/payload.config";
import Image from "next/image";
import { getPayload } from "payload";
export const metadata = {
title:
"Slick Blogs Single || Resonance — One & Multi Page React Nextjs Creative Template",
description:
"Resonance — One & Multi Page React Nextjs Creative Template",
};
export default async function BlogRead({
params,
}: {
params: Promise<{ slug: string }>;
}) {
const slug = (await params).slug;
const payload = await getPayload({ config: payloadConfig });
const blogData = await payload.find({
collection: "blogs",
where: {
slug: { equals: slug },
},
pagination: false,
});
console.log("data", blogData);
const blog = allBlogs.filter((elm) => elm.id == 34)[0] || allBlogs[0];
return (
<>
<section
className="page-section bg-gradient-gray-light-1 bg-scroll overflow-hidden"
id="home"
>
{/* <!-- Background Shape --> */}
<div className="bg-shape-1 wow fadeIn">
<Image
src="/assets/images/demo-fancy/bg-shape-1.svg"
width={1443}
height={844}
alt=""
/>
</div>
{/* <!-- End Background Shape --> */}
<div className="container position-relative pt-sm-40 text-center">
<div className="row">
<div className="col-md-10 offset-md-1 col-lg-8 offset-lg-2">
<h1 className="hs-title-10 mb-10 wow fadeInUp">
{/* @ts-ignore */}
{blog?.title || blog?.postTitle}
</h1>
{/* Author, Categories, Comments */}
<div
className="blog-item-data mb-0 wow fadeIn"
data-wow-delay="0.2s"
>
<div className="d-inline-block me-3">
<a href="#">
<i className="mi-clock size-16" />
<span className="visually-hidden">Date:</span> December 25
</a>
</div>
<div className="d-inline-block me-3">
<a href="#">
<i className="mi-user size-16" />
<span className="visually-hidden">Author:</span> John Doe
</a>
</div>
<div className="d-inline-block me-3">
<i className="mi-folder size-16" />
<span className="visually-hidden">Categories:</span>
<a href="#">Design</a>, <a href="#">Branding</a>
</div>
<div className="d-inline-block me-3">
<a href="#">
<i className="mi-message size-16" /> 5 Comments
</a>
</div>
</div>
{/* End Author, Categories, Comments */}
</div>
</div>
</div>
</section>
<>
{/* Section */}
<section className="page-section">
<div className="container relative">
<div className="row">
{/* Content */}
<div className="col-md-10 offset-md-1 col-lg-8 offset-lg-2">
{/* Post */}
<div className="blog-item mb-80 mb-xs-40">
<div className="blog-item-body">
<div className="mb-40 mb-xs-30">
<Image
src="/assets/images/demo-fancy/blog/post-prev-3-large.jpg"
alt="Image Description"
width={1350}
height={759}
className="round"
/>
</div>
<p>
Morbi lacus massa, euismod ut turpis molestie, tristique
sodales est. Integer sit amet mi id sapien tempor molestie
in nec massa. Fusce non ante sed lorem rutrum feugiat.
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Mauris non laoreet dui. Morbi lacus massa, euismod ut
turpis molestie, tristique sodales est. Integer sit amet
mi id sapien tempor molestie in nec massa.
</p>
<p>
Fusce non ante sed lorem rutrum feugiat. Vestibulum
pellentesque, purus ut&nbsp;dignissim consectetur, nulla
erat ultrices purus, ut&nbsp;consequat sem elit non sem.
Morbi lacus massa, euismod ut turpis molestie, tristique
sodales est. Integer sit amet mi id sapien tempor molestie
in nec massa. Fusce non ante sed lorem rutrum feugiat.
</p>
<blockquote>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Integer posuere erat a&nbsp;ante. Vestibulum
pellentesque, purus ut dignissim consectetur, nulla erat
ultrices purus.
</p>
<footer>
Someone famous in
<cite title="Source Title"> Source Title </cite>
</footer>
</blockquote>
<p>
Praesent ultricies ut ipsum non laoreet. Nunc ac
<a href="#">ultricies</a> leo. Nulla ac ultrices arcu.
Nullam adipiscing lacus in consectetur posuere. Nunc
malesuada tellus turpis, ac pretium orci molestie vel.
Morbi lacus massa, euismod ut turpis molestie, tristique
sodales est. Integer sit amet mi id sapien tempor molestie
in nec massa. Fusce non ante sed lorem rutrum feugiat.
</p>
<ul>
<li>First item of the list</li>
<li>Second item of the list</li>
<li>Third item of the list</li>
</ul>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Mauris non laoreet dui. Morbi lacus massa, euismod ut
turpis molestie, tristique sodales est. Integer sit amet
mi id sapien tempor molestie in nec massa. Fusce non ante
sed lorem rutrum feugiat. Vestibulum pellentesque, purus
ut&nbsp;dignissim consectetur, nulla erat ultrices purus,
ut&nbsp;consequat sem elit non sem.
</p>
</div>
</div>
{/* End Post */}
{/* Comments */}
<div className="mb-80 mb-xs-40">
<h4 className="blog-page-title">
Comments <small className="number">(3)</small>
</h4>
<ul className="media-list comment-list clearlist">
<BlogComments />
</ul>
</div>
{/* End Comments */}
{/* Add Comment */}
<div className="mb-80 mb-xs-40">
<h4 className="blog-page-title">Leave a comment</h4>
{/* Form */}
<CommentForm />
{/* End Form */}
</div>
{/* End Add Comment */}
{/* Prev/Next Post */}
<div className="clearfix mt-40">
<a href="#" className="blog-item-more circle left">
<i className="mi-chevron-left" />
&nbsp;Prev post
</a>
<a href="#" className="blog-item-more circle right">
Next post&nbsp;
<i className="mi-chevron-right" />
</a>
</div>
{/* End Prev/Next Post */}
</div>
{/* End Content */}
</div>
</div>
</section>
{/* End Section */}
{/* Divider */}
<hr className="mt-0 mb-0" />
{/* End Divider */}
{/* Section */}
<section className="page-section">
<div className="container relative">
<div className="row mt-n60">
<BlogWidget
inputClass="newsletter-field form-control input-md circle mb-10"
btnClass="btn btn-mod btn-color btn-medium btn-circle btn-hover-anim form-control"
/>
</div>
</div>
</section>
</>
</>
);
}

View File

@ -0,0 +1,24 @@
/* THIS FILE WAS GENERATED AUTOMATICALLY BY PAYLOAD. */
/* DO NOT MODIFY IT BECAUSE IT COULD BE REWRITTEN AT ANY TIME. */
import type { Metadata } from 'next'
import config from '@payload-config'
import { NotFoundPage, generatePageMetadata } from '@payloadcms/next/views'
import { importMap } from '../importMap'
type Args = {
params: Promise<{
segments: string[]
}>
searchParams: Promise<{
[key: string]: string | string[]
}>
}
export const generateMetadata = ({ params, searchParams }: Args): Promise<Metadata> =>
generatePageMetadata({ config, params, searchParams })
const NotFound = ({ params, searchParams }: Args) =>
NotFoundPage({ config, params, searchParams, importMap })
export default NotFound

View File

@ -0,0 +1,24 @@
/* THIS FILE WAS GENERATED AUTOMATICALLY BY PAYLOAD. */
/* DO NOT MODIFY IT BECAUSE IT COULD BE REWRITTEN AT ANY TIME. */
import type { Metadata } from 'next'
import config from '@payload-config'
import { RootPage, generatePageMetadata } from '@payloadcms/next/views'
import { importMap } from '../importMap'
type Args = {
params: Promise<{
segments: string[]
}>
searchParams: Promise<{
[key: string]: string | string[]
}>
}
export const generateMetadata = ({ params, searchParams }: Args): Promise<Metadata> =>
generatePageMetadata({ config, params, searchParams })
const Page = ({ params, searchParams }: Args) =>
RootPage({ config, params, searchParams, importMap })
export default Page

View File

@ -0,0 +1,47 @@
import { RscEntryLexicalCell as RscEntryLexicalCell_44fe37237e0ebf4470c9990d8cb7b07e } from '@payloadcms/richtext-lexical/rsc'
import { RscEntryLexicalField as RscEntryLexicalField_44fe37237e0ebf4470c9990d8cb7b07e } from '@payloadcms/richtext-lexical/rsc'
import { InlineToolbarFeatureClient as InlineToolbarFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from '@payloadcms/richtext-lexical/client'
import { HorizontalRuleFeatureClient as HorizontalRuleFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from '@payloadcms/richtext-lexical/client'
import { UploadFeatureClient as UploadFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from '@payloadcms/richtext-lexical/client'
import { BlockquoteFeatureClient as BlockquoteFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from '@payloadcms/richtext-lexical/client'
import { RelationshipFeatureClient as RelationshipFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from '@payloadcms/richtext-lexical/client'
import { LinkFeatureClient as LinkFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from '@payloadcms/richtext-lexical/client'
import { ChecklistFeatureClient as ChecklistFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from '@payloadcms/richtext-lexical/client'
import { OrderedListFeatureClient as OrderedListFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from '@payloadcms/richtext-lexical/client'
import { UnorderedListFeatureClient as UnorderedListFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from '@payloadcms/richtext-lexical/client'
import { IndentFeatureClient as IndentFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from '@payloadcms/richtext-lexical/client'
import { AlignFeatureClient as AlignFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from '@payloadcms/richtext-lexical/client'
import { HeadingFeatureClient as HeadingFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from '@payloadcms/richtext-lexical/client'
import { ParagraphFeatureClient as ParagraphFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from '@payloadcms/richtext-lexical/client'
import { InlineCodeFeatureClient as InlineCodeFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from '@payloadcms/richtext-lexical/client'
import { SuperscriptFeatureClient as SuperscriptFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from '@payloadcms/richtext-lexical/client'
import { SubscriptFeatureClient as SubscriptFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from '@payloadcms/richtext-lexical/client'
import { StrikethroughFeatureClient as StrikethroughFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from '@payloadcms/richtext-lexical/client'
import { UnderlineFeatureClient as UnderlineFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from '@payloadcms/richtext-lexical/client'
import { BoldFeatureClient as BoldFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from '@payloadcms/richtext-lexical/client'
import { ItalicFeatureClient as ItalicFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from '@payloadcms/richtext-lexical/client'
export const importMap = {
"@payloadcms/richtext-lexical/rsc#RscEntryLexicalCell": RscEntryLexicalCell_44fe37237e0ebf4470c9990d8cb7b07e,
"@payloadcms/richtext-lexical/rsc#RscEntryLexicalField": RscEntryLexicalField_44fe37237e0ebf4470c9990d8cb7b07e,
"@payloadcms/richtext-lexical/client#InlineToolbarFeatureClient": InlineToolbarFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
"@payloadcms/richtext-lexical/client#HorizontalRuleFeatureClient": HorizontalRuleFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
"@payloadcms/richtext-lexical/client#UploadFeatureClient": UploadFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
"@payloadcms/richtext-lexical/client#BlockquoteFeatureClient": BlockquoteFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
"@payloadcms/richtext-lexical/client#RelationshipFeatureClient": RelationshipFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
"@payloadcms/richtext-lexical/client#LinkFeatureClient": LinkFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
"@payloadcms/richtext-lexical/client#ChecklistFeatureClient": ChecklistFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
"@payloadcms/richtext-lexical/client#OrderedListFeatureClient": OrderedListFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
"@payloadcms/richtext-lexical/client#UnorderedListFeatureClient": UnorderedListFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
"@payloadcms/richtext-lexical/client#IndentFeatureClient": IndentFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
"@payloadcms/richtext-lexical/client#AlignFeatureClient": AlignFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
"@payloadcms/richtext-lexical/client#HeadingFeatureClient": HeadingFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
"@payloadcms/richtext-lexical/client#ParagraphFeatureClient": ParagraphFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
"@payloadcms/richtext-lexical/client#InlineCodeFeatureClient": InlineCodeFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
"@payloadcms/richtext-lexical/client#SuperscriptFeatureClient": SuperscriptFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
"@payloadcms/richtext-lexical/client#SubscriptFeatureClient": SubscriptFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
"@payloadcms/richtext-lexical/client#StrikethroughFeatureClient": StrikethroughFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
"@payloadcms/richtext-lexical/client#UnderlineFeatureClient": UnderlineFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
"@payloadcms/richtext-lexical/client#BoldFeatureClient": BoldFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
"@payloadcms/richtext-lexical/client#ItalicFeatureClient": ItalicFeatureClient_e70f5e05f09f93e00b997edb1ef0c864
}

View File

@ -0,0 +1,19 @@
/* THIS FILE WAS GENERATED AUTOMATICALLY BY PAYLOAD. */
/* DO NOT MODIFY IT BECAUSE IT COULD BE REWRITTEN AT ANY TIME. */
import config from '@payload-config'
import '@payloadcms/next/css'
import {
REST_DELETE,
REST_GET,
REST_OPTIONS,
REST_PATCH,
REST_POST,
REST_PUT,
} from '@payloadcms/next/routes'
export const GET = REST_GET(config)
export const POST = REST_POST(config)
export const DELETE = REST_DELETE(config)
export const PATCH = REST_PATCH(config)
export const PUT = REST_PUT(config)
export const OPTIONS = REST_OPTIONS(config)

View File

@ -0,0 +1,7 @@
/* THIS FILE WAS GENERATED AUTOMATICALLY BY PAYLOAD. */
/* DO NOT MODIFY IT BECAUSE IT COULD BE REWRITTEN AT ANY TIME. */
import config from '@payload-config'
import '@payloadcms/next/css'
import { GRAPHQL_PLAYGROUND_GET } from '@payloadcms/next/routes'
export const GET = GRAPHQL_PLAYGROUND_GET(config)

View File

@ -0,0 +1,8 @@
/* THIS FILE WAS GENERATED AUTOMATICALLY BY PAYLOAD. */
/* DO NOT MODIFY IT BECAUSE IT COULD BE REWRITTEN AT ANY TIME. */
import config from '@payload-config'
import { GRAPHQL_POST, REST_OPTIONS } from '@payloadcms/next/routes'
export const POST = GRAPHQL_POST(config)
export const OPTIONS = REST_OPTIONS(config)

View File

View File

@ -0,0 +1,31 @@
/* THIS FILE WAS GENERATED AUTOMATICALLY BY PAYLOAD. */
/* DO NOT MODIFY IT BECAUSE IT COULD BE REWRITTEN AT ANY TIME. */
import config from '@payload-config'
import '@payloadcms/next/css'
import type { ServerFunctionClient } from 'payload'
import { handleServerFunctions, RootLayout } from '@payloadcms/next/layouts'
import React from 'react'
import { importMap } from './admin/importMap.js'
import './custom.scss'
type Args = {
children: React.ReactNode
}
const serverFunction: ServerFunctionClient = async function (args) {
'use server'
return handleServerFunctions({
...args,
config,
importMap,
})
}
const Layout = ({ children }: Args) => (
<RootLayout config={config} importMap={importMap} serverFunction={serverFunction}>
{children}
</RootLayout>
)
export default Layout

View File

@ -0,0 +1,19 @@
import React from 'react'
import './styles.css'
export const metadata = {
description: 'A blank template using Payload in a Next.js app.',
title: 'Payload Blank Template',
}
export default async function RootLayout(props: { children: React.ReactNode }) {
const { children } = props
return (
<html lang="en">
<body>
<main>{children}</main>
</body>
</html>
)
}

View File

@ -0,0 +1,59 @@
import { headers as getHeaders } from 'next/headers.js'
import Image from 'next/image'
import { getPayload } from 'payload'
import React from 'react'
import { fileURLToPath } from 'url'
import config from '@/payload.config'
import './styles.css'
export default async function HomePage() {
const headers = await getHeaders()
const payloadConfig = await config
const payload = await getPayload({ config: payloadConfig })
const { user } = await payload.auth({ headers })
const fileURL = `vscode://file/${fileURLToPath(import.meta.url)}`
return (
<div className="home">
<div className="content">
<picture>
<source srcSet="https://raw.githubusercontent.com/payloadcms/payload/main/packages/ui/src/assets/payload-favicon.svg" />
<Image
alt="Payload Logo"
height={65}
src="https://raw.githubusercontent.com/payloadcms/payload/main/packages/ui/src/assets/payload-favicon.svg"
width={65}
/>
</picture>
{!user && <h1>Welcome to your new project.</h1>}
{user && <h1>Welcome back, {user.email}</h1>}
<div className="links">
<a
className="admin"
href={payloadConfig.routes.admin}
rel="noopener noreferrer"
target="_blank"
>
Go to admin panel
</a>
<a
className="docs"
href="https://payloadcms.com/docs"
rel="noopener noreferrer"
target="_blank"
>
Documentation
</a>
</div>
</div>
<div className="footer">
<p>Update this page by editing</p>
<a className="codeLink" href={fileURL}>
<code>app/(frontend)/page.tsx</code>
</a>
</div>
</div>
)
}

View File

@ -0,0 +1,164 @@
:root {
--font-mono: 'Roboto Mono', monospace;
}
* {
box-sizing: border-box;
}
html {
font-size: 18px;
line-height: 32px;
background: rgb(0, 0, 0);
-webkit-font-smoothing: antialiased;
}
html,
body,
#app {
height: 100%;
}
body {
font-family: system-ui;
font-size: 18px;
line-height: 32px;
margin: 0;
color: rgb(1000, 1000, 1000);
@media (max-width: 1024px) {
font-size: 15px;
line-height: 24px;
}
}
img {
max-width: 100%;
height: auto;
display: block;
}
h1 {
margin: 40px 0;
font-size: 64px;
line-height: 70px;
font-weight: bold;
@media (max-width: 1024px) {
margin: 24px 0;
font-size: 42px;
line-height: 42px;
}
@media (max-width: 768px) {
font-size: 38px;
line-height: 38px;
}
@media (max-width: 400px) {
font-size: 32px;
line-height: 32px;
}
}
p {
margin: 24px 0;
@media (max-width: 1024px) {
margin: calc(var(--base) * 0.75) 0;
}
}
a {
color: currentColor;
&:focus {
opacity: 0.8;
outline: none;
}
&:active {
opacity: 0.7;
outline: none;
}
}
svg {
vertical-align: middle;
}
.home {
display: flex;
flex-direction: column;
justify-content: space-between;
align-items: center;
height: 100vh;
padding: 45px;
max-width: 1024px;
margin: 0 auto;
overflow: hidden;
@media (max-width: 400px) {
padding: 24px;
}
.content {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
flex-grow: 1;
h1 {
text-align: center;
}
}
.links {
display: flex;
align-items: center;
gap: 12px;
a {
text-decoration: none;
padding: 0.25rem 0.5rem;
border-radius: 4px;
}
.admin {
color: rgb(0, 0, 0);
background: rgb(1000, 1000, 1000);
border: 1px solid rgb(0, 0, 0);
}
.docs {
color: rgb(1000, 1000, 1000);
background: rgb(0, 0, 0);
border: 1px solid rgb(1000, 1000, 1000);
}
}
.footer {
display: flex;
align-items: center;
gap: 8px;
@media (max-width: 1024px) {
flex-direction: column;
gap: 6px;
}
p {
margin: 0;
}
.codeLink {
text-decoration: none;
padding: 0 0.5rem;
background: rgb(60, 60, 60);
border-radius: 4px;
}
}
}

View File

@ -1,7 +0,0 @@
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return <>{children}</>;
}

14
src/app/my-route/route.ts Normal file
View File

@ -0,0 +1,14 @@
import configPromise from '@payload-config'
import { getPayload } from 'payload'
export const GET = async () => {
const payload = await getPayload({
config: configPromise,
})
const data = await payload.find({
collection: 'users',
})
return Response.json(data)
}

31
src/collections/Blogs.ts Normal file
View File

@ -0,0 +1,31 @@
import type { CollectionConfig } from "payload";
import { lexicalEditor } from "@payloadcms/richtext-lexical";
export const Blogs: CollectionConfig = {
slug: "blogs",
fields: [
{
name: "title",
type: "text",
required: true,
},
{
name: "slug",
type: "text",
required: true,
},
{
name: "img",
label: "Image",
type: "upload",
relationTo: "media",
required: true,
},
{
name: "content",
type: "richText",
required: true,
editor: lexicalEditor({}),
},
],
};

16
src/collections/Media.ts Normal file
View File

@ -0,0 +1,16 @@
import type { CollectionConfig } from "payload";
export const Media: CollectionConfig = {
slug: "media",
access: {
read: () => true,
},
fields: [
{
name: "alt",
type: "text",
required: true,
},
],
upload: true,
};

13
src/collections/Users.ts Normal file
View File

@ -0,0 +1,13 @@
import type { CollectionConfig } from "payload";
export const Users: CollectionConfig = {
slug: "users",
admin: {
useAsTitle: "email",
},
auth: true,
fields: [
// Email added by default
// Add more fields as needed
],
};

276
src/payload-types.ts Normal file
View File

@ -0,0 +1,276 @@
/* tslint:disable */
/* eslint-disable */
/**
* This file was automatically generated by Payload.
* DO NOT MODIFY IT BY HAND. Instead, modify your source Payload config,
* and re-run `payload generate:types` to regenerate this file.
*/
export interface Config {
auth: {
users: UserAuthOperations;
};
collections: {
users: User;
media: Media;
blogs: Blog;
'payload-locked-documents': PayloadLockedDocument;
'payload-preferences': PayloadPreference;
'payload-migrations': PayloadMigration;
};
collectionsJoins: {};
collectionsSelect: {
users: UsersSelect<false> | UsersSelect<true>;
media: MediaSelect<false> | MediaSelect<true>;
blogs: BlogsSelect<false> | BlogsSelect<true>;
'payload-locked-documents': PayloadLockedDocumentsSelect<false> | PayloadLockedDocumentsSelect<true>;
'payload-preferences': PayloadPreferencesSelect<false> | PayloadPreferencesSelect<true>;
'payload-migrations': PayloadMigrationsSelect<false> | PayloadMigrationsSelect<true>;
};
db: {
defaultIDType: number;
};
globals: {};
globalsSelect: {};
locale: null;
user: User & {
collection: 'users';
};
jobs: {
tasks: unknown;
workflows: unknown;
};
}
export interface UserAuthOperations {
forgotPassword: {
email: string;
password: string;
};
login: {
email: string;
password: string;
};
registerFirstUser: {
email: string;
password: string;
};
unlock: {
email: string;
password: string;
};
}
/**
* This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "users".
*/
export interface User {
id: number;
updatedAt: string;
createdAt: string;
email: string;
resetPasswordToken?: string | null;
resetPasswordExpiration?: string | null;
salt?: string | null;
hash?: string | null;
loginAttempts?: number | null;
lockUntil?: string | null;
password?: string | null;
}
/**
* This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "media".
*/
export interface Media {
id: number;
alt: string;
prefix?: string | null;
updatedAt: string;
createdAt: string;
url?: string | null;
thumbnailURL?: string | null;
filename?: string | null;
mimeType?: string | null;
filesize?: number | null;
width?: number | null;
height?: number | null;
focalX?: number | null;
focalY?: number | null;
}
/**
* This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "blogs".
*/
export interface Blog {
id: number;
title: string;
slug: string;
img: number | Media;
content: {
root: {
type: string;
children: {
type: string;
version: number;
[k: string]: unknown;
}[];
direction: ('ltr' | 'rtl') | null;
format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | '';
indent: number;
version: number;
};
[k: string]: unknown;
};
updatedAt: string;
createdAt: string;
}
/**
* This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "payload-locked-documents".
*/
export interface PayloadLockedDocument {
id: number;
document?:
| ({
relationTo: 'users';
value: number | User;
} | null)
| ({
relationTo: 'media';
value: number | Media;
} | null)
| ({
relationTo: 'blogs';
value: number | Blog;
} | null);
globalSlug?: string | null;
user: {
relationTo: 'users';
value: number | User;
};
updatedAt: string;
createdAt: string;
}
/**
* This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "payload-preferences".
*/
export interface PayloadPreference {
id: number;
user: {
relationTo: 'users';
value: number | User;
};
key?: string | null;
value?:
| {
[k: string]: unknown;
}
| unknown[]
| string
| number
| boolean
| null;
updatedAt: string;
createdAt: string;
}
/**
* This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "payload-migrations".
*/
export interface PayloadMigration {
id: number;
name?: string | null;
batch?: number | null;
updatedAt: string;
createdAt: string;
}
/**
* This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "users_select".
*/
export interface UsersSelect<T extends boolean = true> {
updatedAt?: T;
createdAt?: T;
email?: T;
resetPasswordToken?: T;
resetPasswordExpiration?: T;
salt?: T;
hash?: T;
loginAttempts?: T;
lockUntil?: T;
}
/**
* This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "media_select".
*/
export interface MediaSelect<T extends boolean = true> {
alt?: T;
prefix?: T;
updatedAt?: T;
createdAt?: T;
url?: T;
thumbnailURL?: T;
filename?: T;
mimeType?: T;
filesize?: T;
width?: T;
height?: T;
focalX?: T;
focalY?: T;
}
/**
* This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "blogs_select".
*/
export interface BlogsSelect<T extends boolean = true> {
title?: T;
slug?: T;
img?: T;
content?: T;
updatedAt?: T;
createdAt?: T;
}
/**
* This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "payload-locked-documents_select".
*/
export interface PayloadLockedDocumentsSelect<T extends boolean = true> {
document?: T;
globalSlug?: T;
user?: T;
updatedAt?: T;
createdAt?: T;
}
/**
* This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "payload-preferences_select".
*/
export interface PayloadPreferencesSelect<T extends boolean = true> {
user?: T;
key?: T;
value?: T;
updatedAt?: T;
createdAt?: T;
}
/**
* This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "payload-migrations_select".
*/
export interface PayloadMigrationsSelect<T extends boolean = true> {
name?: T;
batch?: T;
updatedAt?: T;
createdAt?: T;
}
/**
* This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "auth".
*/
export interface Auth {
[k: string]: unknown;
}
declare module 'payload' {
export interface GeneratedTypes extends Config {}
}

56
src/payload.config.ts Normal file
View File

@ -0,0 +1,56 @@
// storage-adapter-import-placeholder
import { postgresAdapter } from "@payloadcms/db-postgres";
import { payloadCloudPlugin } from "@payloadcms/payload-cloud";
import { s3Storage } from "@payloadcms/storage-s3";
import path from "path";
import { buildConfig } from "payload";
import { fileURLToPath } from "url";
import sharp from "sharp";
import { Users } from "./collections/Users";
import { Media } from "./collections/Media";
import { Blogs } from "./collections/Blogs";
const filename = fileURLToPath(import.meta.url);
const dirname = path.dirname(filename);
export default buildConfig({
admin: {
user: Users.slug,
importMap: {
baseDir: path.resolve(dirname),
},
},
collections: [Users, Media, Blogs],
secret: process.env.PAYLOAD_SECRET || "",
typescript: {
outputFile: path.resolve(dirname, "payload-types.ts"),
},
db: postgresAdapter({
pool: {
connectionString: process.env.DATABASE_URI || "",
},
}),
sharp,
plugins: [
payloadCloudPlugin(),
// storage-adapter-placeholder
s3Storage({
collections: {
media: {
prefix: "media",
},
},
bucket: process.env.S3_BUCKET || "",
config: {
forcePathStyle: true, // Important for using Supabase
credentials: {
accessKeyId: process.env.S3_ACCESS_KEY_ID || "",
secretAccessKey: process.env.S3_SECRET_ACCESS_KEY || "",
},
region: process.env.S3_REGION,
endpoint: process.env.S3_ENDPOINT,
},
}),
],
});

View File

@ -1,8 +1,9 @@
// @ts-nocheck
/* eslint-disable @typescript-eslint/no-require-imports */
// @ts-nocheck
export function init_wow() {
const { WOW } = require("wowjs");
const WOW = require("wow.js");
setTimeout(() => {
/* Wow init */
if (document.body.classList.contains("appear-animate")) {
@ -14,13 +15,11 @@ export function init_wow() {
boxClass: "wow",
animateClass: "animatedfgfg",
offset: 100,
live: false,
callback: function (box) {
box.classList.add("animated");
},
});
if (document.body.classList.contains("appear-animate")) {
wow.init();
} else {
@ -28,7 +27,6 @@ export function init_wow() {
.querySelectorAll(".wow")
.forEach((el) => (el.style.opacity = "1"));
}
/* Wow for portfolio init */
if (document.body.classList.contains("appear-animate")) {
document
@ -39,13 +37,11 @@ export function init_wow() {
boxClass: "wow-p",
animateClass: "animatedfgfg",
offset: 100,
live: false,
callback: function (box) {
box.classList.add("animated");
},
});
if (document.body.classList.contains("appear-animate")) {
wow_p.init();
} else {
@ -53,7 +49,6 @@ export function init_wow() {
.querySelectorAll(".wow-p")
.forEach((el) => (el.style.opacity = "1"));
}
/* Wow for menu bar init */
if (
document.body.classList.contains("appear-animate") &&

View File

@ -1,7 +1,11 @@
{
"compilerOptions": {
"target": "ES2017",
"lib": ["dom", "dom.iterable", "esnext"],
"lib": [
"dom",
"dom.iterable",
"esnext"
],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
@ -19,10 +23,25 @@
}
],
"paths": {
"@/*": ["./src/*"],
"@public/*": ["./public/*"]
"@/*": [
"./src/*"
],
"@public/*": [
"./public/*"
],
"@payload-config": [
"./src/payload.config.ts"
]
}
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts", "src/utils/initWow.js"],
"exclude": ["node_modules"]
}
"include": [
"next-env.d.ts",
"**/*.ts",
"**/*.tsx",
".next/types/**/*.ts",
"src/utils/initWow.js"
],
"exclude": [
"node_modules"
]
}