initial commit
This commit is contained in:
34
src/app/(app)/layout.tsx
Normal file
34
src/app/(app)/layout.tsx
Normal file
@@ -0,0 +1,34 @@
|
||||
import type { Metadata } from "next";
|
||||
import { Geist, Geist_Mono } from "next/font/google";
|
||||
import "../globals.css";
|
||||
|
||||
const geistSans = Geist({
|
||||
variable: "--font-geist-sans",
|
||||
subsets: ["latin"],
|
||||
});
|
||||
|
||||
const geistMono = Geist_Mono({
|
||||
variable: "--font-geist-mono",
|
||||
subsets: ["latin"],
|
||||
});
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "Liam Pietralla",
|
||||
description: "Enthusiastic Software Developer & DevOps Engineer",
|
||||
};
|
||||
|
||||
export default function RootLayout({
|
||||
children,
|
||||
}: Readonly<{
|
||||
children: React.ReactNode;
|
||||
}>) {
|
||||
return (
|
||||
<html lang="en">
|
||||
<body
|
||||
className={`${geistSans.variable} ${geistMono.variable} antialiased`}
|
||||
>
|
||||
{children}
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
40
src/app/(app)/page.tsx
Normal file
40
src/app/(app)/page.tsx
Normal file
@@ -0,0 +1,40 @@
|
||||
export const dynamic = 'force-dynamic'
|
||||
|
||||
import IndexLink from "@/components/home-page-link";
|
||||
import Rule from "@/components/horizontal-rule";
|
||||
import { getHome } from "@/services/home-service";
|
||||
import { Mail } from "lucide-react";
|
||||
import Image from "next/image";
|
||||
|
||||
const IndexPage = async () => {
|
||||
const home = await getHome();
|
||||
|
||||
return (
|
||||
<div className="flex flex-col gap-4 justify-center items-center h-screen">
|
||||
<Image className="rounded-full" src="/images/liam_pietralla.jpg" width={200} height={200} alt="Liam Pietralla" />
|
||||
<h1 className="text-5xl font-bold">Liam Pietralla</h1>
|
||||
<h2 className="text-xl">Enthusiastic Software Developer & DevOps Engineer</h2>
|
||||
<Rule className="w-[300px]" />
|
||||
<div className="flex flex-row gap-4">
|
||||
{home.mainLinks.map(link => (
|
||||
<IndexLink key={link.id} {...link} />
|
||||
))}
|
||||
</div>
|
||||
<div className="flex flex-row gap-4">
|
||||
{home.popoverLinks.map(link => (
|
||||
<IndexLink key={link.id} {...link} isPopover={true} />
|
||||
))}
|
||||
</div>
|
||||
<Rule className="w-[300px]" />
|
||||
<a href="mailto:me@liampietralla.com" className="group leading-relaxed">
|
||||
<span className="flex flex-row gap-2">
|
||||
<Mail />
|
||||
me@liampietralla.com
|
||||
</span>
|
||||
<span className="block max-w-0 group-hover:max-w-full transition-all duration-500 h-0.5 bg-white"></span>
|
||||
</a>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default IndexPage;
|
||||
35
src/app/(app)/projects/page.tsx
Normal file
35
src/app/(app)/projects/page.tsx
Normal file
@@ -0,0 +1,35 @@
|
||||
export const dynamic = 'force-dynamic'
|
||||
|
||||
import ProjectCard from "@/components/project-card";
|
||||
import Rule from "@/components/horizontal-rule";
|
||||
import { getProjects } from "@/services/projects-service";
|
||||
import Image from "next/image";
|
||||
import Link from "next/link";
|
||||
import { Fragment } from "react";
|
||||
|
||||
const ProjectsPage = async () => {
|
||||
const projects = await getProjects();
|
||||
return (
|
||||
<div className="flex flex-col gap-4 justify-center items-center my-15">
|
||||
<div className="flex flex-row items-center gap-2 my-2">
|
||||
<Image src="/images/liam_pietralla.jpg" width={50} height={50} alt="Liam Pietralla" className="rounded-full" />
|
||||
<Link href="/" className="group leading-relaxed font-semi-bold">
|
||||
Liam Pietralla
|
||||
<span className="block max-w-0 group-hover:max-w-full transition-all duration-500 h-0.5 bg-white"></span>
|
||||
</Link>
|
||||
</div>
|
||||
<h1 className="text-5xl font-bold">Projects</h1>
|
||||
<h2>A collection of interesting projects that I am working on currently or have worked on in the past.</h2>
|
||||
<div className="flex flex-col gap-4">
|
||||
{projects.docs.map((project, index) => (
|
||||
<Fragment key={index}>
|
||||
<ProjectCard {...project} />
|
||||
{index < projects.docs.length - 1 && <Rule />}
|
||||
</Fragment>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default ProjectsPage;
|
||||
24
src/app/(payload)/admin/[[...segments]]/not-found.tsx
Normal file
24
src/app/(payload)/admin/[[...segments]]/not-found.tsx
Normal 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
|
||||
24
src/app/(payload)/admin/[[...segments]]/page.tsx
Normal file
24
src/app/(payload)/admin/[[...segments]]/page.tsx
Normal 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
|
||||
5
src/app/(payload)/admin/importMap.js
Normal file
5
src/app/(payload)/admin/importMap.js
Normal file
@@ -0,0 +1,5 @@
|
||||
|
||||
|
||||
export const importMap = {
|
||||
|
||||
}
|
||||
43
src/app/(payload)/api/[...slug]/route.ts
Normal file
43
src/app/(payload)/api/[...slug]/route.ts
Normal file
@@ -0,0 +1,43 @@
|
||||
/* 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'
|
||||
|
||||
type NextCtx = { params: Promise<{ slug?: string[] }> }
|
||||
type PayloadCtx = { params: Promise<{ slug: string[] }> }
|
||||
|
||||
const coerceCtx = (ctx: NextCtx): PayloadCtx => ({
|
||||
params: ctx.params.then(p => ({ slug: p?.slug ?? [] })),
|
||||
})
|
||||
|
||||
export function GET(req: Request, ctx: NextCtx) {
|
||||
return REST_GET(config)(req, coerceCtx(ctx))
|
||||
}
|
||||
|
||||
export function POST(req: Request, ctx: NextCtx) {
|
||||
return REST_POST(config)(req, coerceCtx(ctx))
|
||||
}
|
||||
|
||||
export function DELETE(req: Request, ctx: NextCtx) {
|
||||
return REST_DELETE(config)(req, coerceCtx(ctx))
|
||||
}
|
||||
|
||||
export function PATCH(req: Request, ctx: NextCtx) {
|
||||
return REST_PATCH(config)(req, coerceCtx(ctx))
|
||||
}
|
||||
|
||||
export function PUT(req: Request, ctx: NextCtx) {
|
||||
return REST_PUT(config)(req, coerceCtx(ctx))
|
||||
}
|
||||
|
||||
export function OPTIONS(req: Request, ctx: NextCtx) {
|
||||
return REST_OPTIONS(config)(req, coerceCtx(ctx))
|
||||
}
|
||||
9
src/app/(payload)/api/graphql-playground/route.ts
Normal file
9
src/app/(payload)/api/graphql-playground/route.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
/* 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 async function GET(req: Request): Promise<Response> {
|
||||
return GRAPHQL_PLAYGROUND_GET(config)(req)
|
||||
}
|
||||
19
src/app/(payload)/api/graphql/route.ts
Normal file
19
src/app/(payload)/api/graphql/route.ts
Normal 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 { GRAPHQL_POST, REST_OPTIONS } from '@payloadcms/next/routes'
|
||||
|
||||
type NextCtx = { params: Promise<{ slug?: string[] }> }
|
||||
type PayloadCtx = { params: Promise<{ slug: string[] }> }
|
||||
|
||||
const coerceCtx = (ctx: NextCtx): PayloadCtx => ({
|
||||
params: ctx.params.then(p => ({ slug: p?.slug ?? [] })),
|
||||
})
|
||||
|
||||
export function POST(req: Request) {
|
||||
return GRAPHQL_POST(config)(req)
|
||||
}
|
||||
|
||||
export function OPTIONS(req: Request, ctx: NextCtx) {
|
||||
return REST_OPTIONS(config)(req, coerceCtx(ctx))
|
||||
}
|
||||
0
src/app/(payload)/custom.scss
Normal file
0
src/app/(payload)/custom.scss
Normal file
31
src/app/(payload)/layout.tsx
Normal file
31
src/app/(payload)/layout.tsx
Normal 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
|
||||
13
src/app/api/health/route.ts
Normal file
13
src/app/api/health/route.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
export async function GET() {
|
||||
const json = require("../../../../package.json");
|
||||
const response = {
|
||||
"status": "Healthy",
|
||||
"version": json.version
|
||||
}
|
||||
return new Response(JSON.stringify(response), {
|
||||
status: 200,
|
||||
headers: {
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
});
|
||||
}
|
||||
BIN
src/app/favicon.ico
Normal file
BIN
src/app/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
19
src/app/globals.css
Normal file
19
src/app/globals.css
Normal file
@@ -0,0 +1,19 @@
|
||||
@import "tailwindcss";
|
||||
|
||||
:root {
|
||||
--background: #0a0a0a;
|
||||
--foreground: #ededed;
|
||||
}
|
||||
|
||||
@theme inline {
|
||||
--color-background: var(--background);
|
||||
--color-foreground: var(--foreground);
|
||||
--font-sans: var(--font-geist-sans);
|
||||
--font-mono: var(--font-geist-mono);
|
||||
}
|
||||
|
||||
body {
|
||||
background: var(--background);
|
||||
color: var(--foreground);
|
||||
font-family: Arial, Helvetica, sans-serif;
|
||||
}
|
||||
27
src/collections/Media.ts
Normal file
27
src/collections/Media.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
import type { CollectionConfig } from 'payload'
|
||||
|
||||
export const Media: CollectionConfig = {
|
||||
slug: 'media',
|
||||
access: {
|
||||
read: () => true,
|
||||
},
|
||||
fields: [
|
||||
{
|
||||
name: 'alt',
|
||||
type: 'text',
|
||||
required: true,
|
||||
},
|
||||
],
|
||||
upload: {
|
||||
staticDir: 'portfolio-data/media',
|
||||
imageSizes: [
|
||||
{
|
||||
name: "thumbnail",
|
||||
width: 150,
|
||||
height: 150,
|
||||
position: 'centre',
|
||||
}
|
||||
],
|
||||
adminThumbnail: 'thumbnail',
|
||||
}
|
||||
}
|
||||
48
src/collections/Projects.ts
Normal file
48
src/collections/Projects.ts
Normal file
@@ -0,0 +1,48 @@
|
||||
import { CollectionConfig } from "payload";
|
||||
|
||||
export const Projects: CollectionConfig = {
|
||||
slug: "project",
|
||||
access: {
|
||||
read: () => true,
|
||||
},
|
||||
fields: [
|
||||
{
|
||||
name: "title",
|
||||
type: "text",
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
name: "description",
|
||||
type: "textarea",
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
name: "featuredImage",
|
||||
type: "relationship",
|
||||
relationTo: "media",
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
name: "tags",
|
||||
type: "array",
|
||||
required: false,
|
||||
fields: [
|
||||
{
|
||||
name: "tag",
|
||||
type: "text",
|
||||
required: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "viewLink",
|
||||
type: "text",
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
name: "repositoryLink",
|
||||
type: "text",
|
||||
required: false,
|
||||
}
|
||||
]
|
||||
}
|
||||
13
src/collections/Users.ts
Normal file
13
src/collections/Users.ts
Normal 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
|
||||
],
|
||||
}
|
||||
60
src/components/home-page-link.tsx
Normal file
60
src/components/home-page-link.tsx
Normal file
@@ -0,0 +1,60 @@
|
||||
import Link from "next/link";
|
||||
import { DynamicIcon, IconName } from 'lucide-react/dynamic';
|
||||
|
||||
interface HomePageLinkProps {
|
||||
title: string;
|
||||
url: string;
|
||||
icon: string;
|
||||
id?: string | null;
|
||||
isPopover?: boolean;
|
||||
}
|
||||
|
||||
const HomePageLink = ({ title, icon, url, isPopover }: HomePageLinkProps) => {
|
||||
const isRelative = !url.startsWith("http");
|
||||
const dynIcon = <DynamicIcon name={icon as IconName} />
|
||||
|
||||
if (isPopover) {
|
||||
if (isRelative) {
|
||||
return (
|
||||
<div className="relative group">
|
||||
<Link href={url} className="flex items-center space-x-2">
|
||||
{dynIcon}
|
||||
</Link>
|
||||
<div className="absolute left-1/2 -translate-x-1/2 z-10 hidden p-2 px-4 text-sm text-black bg-white rounded-md group-hover:block text-center">
|
||||
{title}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
} else {
|
||||
return (
|
||||
<div className="relative group">
|
||||
<a href={url} className="flex items-center space-x-2">
|
||||
{dynIcon}
|
||||
</a>
|
||||
<div className="absolute left-1/2 -translate-x-1/2 z-10 hidden p-2 px-4 text-sm text-black bg-white rounded-md group-hover:block text-center">
|
||||
{title}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
} else {
|
||||
if (isRelative) {
|
||||
return (
|
||||
<Link href={url} className="group leading-relaxed">
|
||||
<span className="flex flex-row gap-2">{dynIcon} {title}</span>
|
||||
<span className="block max-w-0 group-hover:max-w-full transition-all duration-500 h-0.5 bg-white"></span>
|
||||
</Link>
|
||||
)
|
||||
} else {
|
||||
return (
|
||||
<a href={url} className="group leading-relaxed">
|
||||
<span className="flex flex-row gap-2">{dynIcon} {title}</span>
|
||||
<span className="block max-w-0 group-hover:max-w-full transition-all duration-500 h-0.5 bg-white"></span>
|
||||
</a>
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export default HomePageLink;
|
||||
13
src/components/horizontal-rule.tsx
Normal file
13
src/components/horizontal-rule.tsx
Normal file
@@ -0,0 +1,13 @@
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
interface RuleProps {
|
||||
className?: string;
|
||||
}
|
||||
|
||||
const HorizontalRule = ({ className }: RuleProps) => {
|
||||
return (
|
||||
<div className={cn("border-t-1 border-accent", className)} />
|
||||
)
|
||||
}
|
||||
|
||||
export default HorizontalRule;
|
||||
48
src/components/project-card.tsx
Normal file
48
src/components/project-card.tsx
Normal file
@@ -0,0 +1,48 @@
|
||||
import Image from "next/image";
|
||||
import HorizontalRule from "./horizontal-rule";
|
||||
import { Code, ExternalLink } from "lucide-react";
|
||||
import { Project } from "@/payload-types";
|
||||
|
||||
const ProjectCard = (project: Project) => {
|
||||
return (
|
||||
<div className="border border-white rounded-md p-4 flex flex-col gap-2 max-w-[700px] mx-auto">
|
||||
<h2 className="text-2xl font-bold">{project.title}</h2>
|
||||
<div className="flex flex-col gap-2">
|
||||
{project.featuredImage && typeof project.featuredImage === "object" && (
|
||||
<Image src={project.featuredImage.url!} alt={project.title} width={project.featuredImage.width!} height={project.featuredImage.height!} className="rounded-md border border-gray-600" />
|
||||
)}
|
||||
<p className="whitespace-pre-wrap">{project.description}</p>
|
||||
<div className="flex flex-row gap-2 my-2">
|
||||
{(project?.tags || []).map((tag) => (
|
||||
<span key={tag.id} className="bg-white text-black rounded-md px-1 py-0.5 text-sm hover:bg-gray-200">
|
||||
{tag.tag}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
<HorizontalRule />
|
||||
<div className="flex flex-row gap-4">
|
||||
{project.viewLink && (
|
||||
<a href={project.viewLink} target="_blank" className="group">
|
||||
<span className="flex flex-row gap-2">
|
||||
<ExternalLink />
|
||||
View Project
|
||||
</span>
|
||||
<span className="block max-w-0 group-hover:max-w-full transition-all duration-500 h-0.5 bg-white"></span>
|
||||
</a>
|
||||
)}
|
||||
{project.repositoryLink && (
|
||||
<a href={project.repositoryLink} target="_blank" className="group">
|
||||
<span className="flex flex-row gap-2">
|
||||
<Code />
|
||||
View Source
|
||||
</span>
|
||||
<span className="block max-w-0 group-hover:max-w-full transition-all duration-500 h-0.5 bg-white"></span>
|
||||
</a>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default ProjectCard;
|
||||
57
src/globals/home.ts
Normal file
57
src/globals/home.ts
Normal file
@@ -0,0 +1,57 @@
|
||||
import { lucideOptions } from "@/lib/lucid-options";
|
||||
import { GlobalConfig } from "payload";
|
||||
|
||||
export const Home: GlobalConfig = {
|
||||
slug: "home",
|
||||
access: {
|
||||
read: () => true,
|
||||
},
|
||||
fields: [
|
||||
{
|
||||
name: "mainLinks",
|
||||
type: "array",
|
||||
required: true,
|
||||
fields: [
|
||||
{
|
||||
name: "title",
|
||||
type: "text",
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
name: "url",
|
||||
type: "text",
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
name: "icon",
|
||||
type: "select",
|
||||
options: lucideOptions,
|
||||
required: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "popoverLinks",
|
||||
type: "array",
|
||||
required: true,
|
||||
fields: [
|
||||
{
|
||||
name: "title",
|
||||
type: "text",
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
name: "url",
|
||||
type: "text",
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
name: "icon",
|
||||
type: "select",
|
||||
options: lucideOptions,
|
||||
required: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
}
|
||||
6
src/lib/lucid-options.ts
Normal file
6
src/lib/lucid-options.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
export const lucideOptions: { label: string, value: string }[] = [
|
||||
{ label: "Code 2", value: "code-2" },
|
||||
{ label: "Notebook", value: "notebook" },
|
||||
{ label: "Github", value: "github" },
|
||||
{ label: "Linkedin", value: "linkedin" },
|
||||
]
|
||||
6
src/lib/utils.ts
Normal file
6
src/lib/utils.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
import { clsx, type ClassValue } from "clsx"
|
||||
import { twMerge } from "tailwind-merge"
|
||||
|
||||
export function cn(...inputs: ClassValue[]) {
|
||||
return twMerge(clsx(inputs))
|
||||
}
|
||||
1183
src/migrations/20250828_224637.json
Normal file
1183
src/migrations/20250828_224637.json
Normal file
File diff suppressed because it is too large
Load Diff
193
src/migrations/20250828_224637.ts
Normal file
193
src/migrations/20250828_224637.ts
Normal file
@@ -0,0 +1,193 @@
|
||||
import { MigrateUpArgs, MigrateDownArgs, sql } from '@payloadcms/db-sqlite'
|
||||
|
||||
export async function up({ db }: MigrateUpArgs): Promise<void> {
|
||||
await db.run(sql`CREATE TABLE \`users_sessions\` (
|
||||
\`_order\` integer NOT NULL,
|
||||
\`_parent_id\` integer NOT NULL,
|
||||
\`id\` text PRIMARY KEY NOT NULL,
|
||||
\`created_at\` text,
|
||||
\`expires_at\` text NOT NULL,
|
||||
FOREIGN KEY (\`_parent_id\`) REFERENCES \`users\`(\`id\`) ON UPDATE no action ON DELETE cascade
|
||||
);
|
||||
`)
|
||||
await db.run(sql`CREATE INDEX \`users_sessions_order_idx\` ON \`users_sessions\` (\`_order\`);`)
|
||||
await db.run(sql`CREATE INDEX \`users_sessions_parent_id_idx\` ON \`users_sessions\` (\`_parent_id\`);`)
|
||||
await db.run(sql`CREATE TABLE \`users\` (
|
||||
\`id\` integer PRIMARY KEY NOT NULL,
|
||||
\`updated_at\` text DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')) NOT NULL,
|
||||
\`created_at\` text DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')) NOT NULL,
|
||||
\`email\` text NOT NULL,
|
||||
\`reset_password_token\` text,
|
||||
\`reset_password_expiration\` text,
|
||||
\`salt\` text,
|
||||
\`hash\` text,
|
||||
\`login_attempts\` numeric DEFAULT 0,
|
||||
\`lock_until\` text
|
||||
);
|
||||
`)
|
||||
await db.run(sql`CREATE INDEX \`users_updated_at_idx\` ON \`users\` (\`updated_at\`);`)
|
||||
await db.run(sql`CREATE INDEX \`users_created_at_idx\` ON \`users\` (\`created_at\`);`)
|
||||
await db.run(sql`CREATE UNIQUE INDEX \`users_email_idx\` ON \`users\` (\`email\`);`)
|
||||
await db.run(sql`CREATE TABLE \`media\` (
|
||||
\`id\` integer PRIMARY KEY NOT NULL,
|
||||
\`alt\` text NOT NULL,
|
||||
\`updated_at\` text DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')) NOT NULL,
|
||||
\`created_at\` text DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')) NOT NULL,
|
||||
\`url\` text,
|
||||
\`thumbnail_u_r_l\` text,
|
||||
\`filename\` text,
|
||||
\`mime_type\` text,
|
||||
\`filesize\` numeric,
|
||||
\`width\` numeric,
|
||||
\`height\` numeric,
|
||||
\`focal_x\` numeric,
|
||||
\`focal_y\` numeric,
|
||||
\`sizes_thumbnail_url\` text,
|
||||
\`sizes_thumbnail_width\` numeric,
|
||||
\`sizes_thumbnail_height\` numeric,
|
||||
\`sizes_thumbnail_mime_type\` text,
|
||||
\`sizes_thumbnail_filesize\` numeric,
|
||||
\`sizes_thumbnail_filename\` text
|
||||
);
|
||||
`)
|
||||
await db.run(sql`CREATE INDEX \`media_updated_at_idx\` ON \`media\` (\`updated_at\`);`)
|
||||
await db.run(sql`CREATE INDEX \`media_created_at_idx\` ON \`media\` (\`created_at\`);`)
|
||||
await db.run(sql`CREATE UNIQUE INDEX \`media_filename_idx\` ON \`media\` (\`filename\`);`)
|
||||
await db.run(sql`CREATE INDEX \`media_sizes_thumbnail_sizes_thumbnail_filename_idx\` ON \`media\` (\`sizes_thumbnail_filename\`);`)
|
||||
await db.run(sql`CREATE TABLE \`project_tags\` (
|
||||
\`_order\` integer NOT NULL,
|
||||
\`_parent_id\` integer NOT NULL,
|
||||
\`id\` text PRIMARY KEY NOT NULL,
|
||||
\`tag\` text NOT NULL,
|
||||
FOREIGN KEY (\`_parent_id\`) REFERENCES \`project\`(\`id\`) ON UPDATE no action ON DELETE cascade
|
||||
);
|
||||
`)
|
||||
await db.run(sql`CREATE INDEX \`project_tags_order_idx\` ON \`project_tags\` (\`_order\`);`)
|
||||
await db.run(sql`CREATE INDEX \`project_tags_parent_id_idx\` ON \`project_tags\` (\`_parent_id\`);`)
|
||||
await db.run(sql`CREATE TABLE \`project\` (
|
||||
\`id\` integer PRIMARY KEY NOT NULL,
|
||||
\`title\` text NOT NULL,
|
||||
\`description\` text NOT NULL,
|
||||
\`featured_image_id\` integer,
|
||||
\`view_link\` text,
|
||||
\`repository_link\` text,
|
||||
\`updated_at\` text DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')) NOT NULL,
|
||||
\`created_at\` text DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')) NOT NULL,
|
||||
FOREIGN KEY (\`featured_image_id\`) REFERENCES \`media\`(\`id\`) ON UPDATE no action ON DELETE set null
|
||||
);
|
||||
`)
|
||||
await db.run(sql`CREATE INDEX \`project_featured_image_idx\` ON \`project\` (\`featured_image_id\`);`)
|
||||
await db.run(sql`CREATE INDEX \`project_updated_at_idx\` ON \`project\` (\`updated_at\`);`)
|
||||
await db.run(sql`CREATE INDEX \`project_created_at_idx\` ON \`project\` (\`created_at\`);`)
|
||||
await db.run(sql`CREATE TABLE \`payload_locked_documents\` (
|
||||
\`id\` integer PRIMARY KEY NOT NULL,
|
||||
\`global_slug\` text,
|
||||
\`updated_at\` text DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')) NOT NULL,
|
||||
\`created_at\` text DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')) NOT NULL
|
||||
);
|
||||
`)
|
||||
await db.run(sql`CREATE INDEX \`payload_locked_documents_global_slug_idx\` ON \`payload_locked_documents\` (\`global_slug\`);`)
|
||||
await db.run(sql`CREATE INDEX \`payload_locked_documents_updated_at_idx\` ON \`payload_locked_documents\` (\`updated_at\`);`)
|
||||
await db.run(sql`CREATE INDEX \`payload_locked_documents_created_at_idx\` ON \`payload_locked_documents\` (\`created_at\`);`)
|
||||
await db.run(sql`CREATE TABLE \`payload_locked_documents_rels\` (
|
||||
\`id\` integer PRIMARY KEY NOT NULL,
|
||||
\`order\` integer,
|
||||
\`parent_id\` integer NOT NULL,
|
||||
\`path\` text NOT NULL,
|
||||
\`users_id\` integer,
|
||||
\`media_id\` integer,
|
||||
\`project_id\` integer,
|
||||
FOREIGN KEY (\`parent_id\`) REFERENCES \`payload_locked_documents\`(\`id\`) ON UPDATE no action ON DELETE cascade,
|
||||
FOREIGN KEY (\`users_id\`) REFERENCES \`users\`(\`id\`) ON UPDATE no action ON DELETE cascade,
|
||||
FOREIGN KEY (\`media_id\`) REFERENCES \`media\`(\`id\`) ON UPDATE no action ON DELETE cascade,
|
||||
FOREIGN KEY (\`project_id\`) REFERENCES \`project\`(\`id\`) ON UPDATE no action ON DELETE cascade
|
||||
);
|
||||
`)
|
||||
await db.run(sql`CREATE INDEX \`payload_locked_documents_rels_order_idx\` ON \`payload_locked_documents_rels\` (\`order\`);`)
|
||||
await db.run(sql`CREATE INDEX \`payload_locked_documents_rels_parent_idx\` ON \`payload_locked_documents_rels\` (\`parent_id\`);`)
|
||||
await db.run(sql`CREATE INDEX \`payload_locked_documents_rels_path_idx\` ON \`payload_locked_documents_rels\` (\`path\`);`)
|
||||
await db.run(sql`CREATE INDEX \`payload_locked_documents_rels_users_id_idx\` ON \`payload_locked_documents_rels\` (\`users_id\`);`)
|
||||
await db.run(sql`CREATE INDEX \`payload_locked_documents_rels_media_id_idx\` ON \`payload_locked_documents_rels\` (\`media_id\`);`)
|
||||
await db.run(sql`CREATE INDEX \`payload_locked_documents_rels_project_id_idx\` ON \`payload_locked_documents_rels\` (\`project_id\`);`)
|
||||
await db.run(sql`CREATE TABLE \`payload_preferences\` (
|
||||
\`id\` integer PRIMARY KEY NOT NULL,
|
||||
\`key\` text,
|
||||
\`value\` text,
|
||||
\`updated_at\` text DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')) NOT NULL,
|
||||
\`created_at\` text DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')) NOT NULL
|
||||
);
|
||||
`)
|
||||
await db.run(sql`CREATE INDEX \`payload_preferences_key_idx\` ON \`payload_preferences\` (\`key\`);`)
|
||||
await db.run(sql`CREATE INDEX \`payload_preferences_updated_at_idx\` ON \`payload_preferences\` (\`updated_at\`);`)
|
||||
await db.run(sql`CREATE INDEX \`payload_preferences_created_at_idx\` ON \`payload_preferences\` (\`created_at\`);`)
|
||||
await db.run(sql`CREATE TABLE \`payload_preferences_rels\` (
|
||||
\`id\` integer PRIMARY KEY NOT NULL,
|
||||
\`order\` integer,
|
||||
\`parent_id\` integer NOT NULL,
|
||||
\`path\` text NOT NULL,
|
||||
\`users_id\` integer,
|
||||
FOREIGN KEY (\`parent_id\`) REFERENCES \`payload_preferences\`(\`id\`) ON UPDATE no action ON DELETE cascade,
|
||||
FOREIGN KEY (\`users_id\`) REFERENCES \`users\`(\`id\`) ON UPDATE no action ON DELETE cascade
|
||||
);
|
||||
`)
|
||||
await db.run(sql`CREATE INDEX \`payload_preferences_rels_order_idx\` ON \`payload_preferences_rels\` (\`order\`);`)
|
||||
await db.run(sql`CREATE INDEX \`payload_preferences_rels_parent_idx\` ON \`payload_preferences_rels\` (\`parent_id\`);`)
|
||||
await db.run(sql`CREATE INDEX \`payload_preferences_rels_path_idx\` ON \`payload_preferences_rels\` (\`path\`);`)
|
||||
await db.run(sql`CREATE INDEX \`payload_preferences_rels_users_id_idx\` ON \`payload_preferences_rels\` (\`users_id\`);`)
|
||||
await db.run(sql`CREATE TABLE \`payload_migrations\` (
|
||||
\`id\` integer PRIMARY KEY NOT NULL,
|
||||
\`name\` text,
|
||||
\`batch\` numeric,
|
||||
\`updated_at\` text DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')) NOT NULL,
|
||||
\`created_at\` text DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')) NOT NULL
|
||||
);
|
||||
`)
|
||||
await db.run(sql`CREATE INDEX \`payload_migrations_updated_at_idx\` ON \`payload_migrations\` (\`updated_at\`);`)
|
||||
await db.run(sql`CREATE INDEX \`payload_migrations_created_at_idx\` ON \`payload_migrations\` (\`created_at\`);`)
|
||||
await db.run(sql`CREATE TABLE \`home_main_links\` (
|
||||
\`_order\` integer NOT NULL,
|
||||
\`_parent_id\` integer NOT NULL,
|
||||
\`id\` text PRIMARY KEY NOT NULL,
|
||||
\`title\` text NOT NULL,
|
||||
\`url\` text NOT NULL,
|
||||
\`icon\` text NOT NULL,
|
||||
FOREIGN KEY (\`_parent_id\`) REFERENCES \`home\`(\`id\`) ON UPDATE no action ON DELETE cascade
|
||||
);
|
||||
`)
|
||||
await db.run(sql`CREATE INDEX \`home_main_links_order_idx\` ON \`home_main_links\` (\`_order\`);`)
|
||||
await db.run(sql`CREATE INDEX \`home_main_links_parent_id_idx\` ON \`home_main_links\` (\`_parent_id\`);`)
|
||||
await db.run(sql`CREATE TABLE \`home_popover_links\` (
|
||||
\`_order\` integer NOT NULL,
|
||||
\`_parent_id\` integer NOT NULL,
|
||||
\`id\` text PRIMARY KEY NOT NULL,
|
||||
\`title\` text NOT NULL,
|
||||
\`url\` text NOT NULL,
|
||||
\`icon\` text NOT NULL,
|
||||
FOREIGN KEY (\`_parent_id\`) REFERENCES \`home\`(\`id\`) ON UPDATE no action ON DELETE cascade
|
||||
);
|
||||
`)
|
||||
await db.run(sql`CREATE INDEX \`home_popover_links_order_idx\` ON \`home_popover_links\` (\`_order\`);`)
|
||||
await db.run(sql`CREATE INDEX \`home_popover_links_parent_id_idx\` ON \`home_popover_links\` (\`_parent_id\`);`)
|
||||
await db.run(sql`CREATE TABLE \`home\` (
|
||||
\`id\` integer PRIMARY KEY NOT NULL,
|
||||
\`updated_at\` text,
|
||||
\`created_at\` text
|
||||
);
|
||||
`)
|
||||
}
|
||||
|
||||
export async function down({ db }: MigrateDownArgs): Promise<void> {
|
||||
await db.run(sql`DROP TABLE \`users_sessions\`;`)
|
||||
await db.run(sql`DROP TABLE \`users\`;`)
|
||||
await db.run(sql`DROP TABLE \`media\`;`)
|
||||
await db.run(sql`DROP TABLE \`project_tags\`;`)
|
||||
await db.run(sql`DROP TABLE \`project\`;`)
|
||||
await db.run(sql`DROP TABLE \`payload_locked_documents\`;`)
|
||||
await db.run(sql`DROP TABLE \`payload_locked_documents_rels\`;`)
|
||||
await db.run(sql`DROP TABLE \`payload_preferences\`;`)
|
||||
await db.run(sql`DROP TABLE \`payload_preferences_rels\`;`)
|
||||
await db.run(sql`DROP TABLE \`payload_migrations\`;`)
|
||||
await db.run(sql`DROP TABLE \`home_main_links\`;`)
|
||||
await db.run(sql`DROP TABLE \`home_popover_links\`;`)
|
||||
await db.run(sql`DROP TABLE \`home\`;`)
|
||||
}
|
||||
9
src/migrations/index.ts
Normal file
9
src/migrations/index.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import * as migration_20250828_224637 from './20250828_224637';
|
||||
|
||||
export const migrations = [
|
||||
{
|
||||
up: migration_20250828_224637.up,
|
||||
down: migration_20250828_224637.down,
|
||||
name: '20250828_224637'
|
||||
},
|
||||
];
|
||||
418
src/payload-types.ts
Normal file
418
src/payload-types.ts
Normal file
@@ -0,0 +1,418 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Supported timezones in IANA format.
|
||||
*
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "supportedTimezones".
|
||||
*/
|
||||
export type SupportedTimezones =
|
||||
| 'Pacific/Midway'
|
||||
| 'Pacific/Niue'
|
||||
| 'Pacific/Honolulu'
|
||||
| 'Pacific/Rarotonga'
|
||||
| 'America/Anchorage'
|
||||
| 'Pacific/Gambier'
|
||||
| 'America/Los_Angeles'
|
||||
| 'America/Tijuana'
|
||||
| 'America/Denver'
|
||||
| 'America/Phoenix'
|
||||
| 'America/Chicago'
|
||||
| 'America/Guatemala'
|
||||
| 'America/New_York'
|
||||
| 'America/Bogota'
|
||||
| 'America/Caracas'
|
||||
| 'America/Santiago'
|
||||
| 'America/Buenos_Aires'
|
||||
| 'America/Sao_Paulo'
|
||||
| 'Atlantic/South_Georgia'
|
||||
| 'Atlantic/Azores'
|
||||
| 'Atlantic/Cape_Verde'
|
||||
| 'Europe/London'
|
||||
| 'Europe/Berlin'
|
||||
| 'Africa/Lagos'
|
||||
| 'Europe/Athens'
|
||||
| 'Africa/Cairo'
|
||||
| 'Europe/Moscow'
|
||||
| 'Asia/Riyadh'
|
||||
| 'Asia/Dubai'
|
||||
| 'Asia/Baku'
|
||||
| 'Asia/Karachi'
|
||||
| 'Asia/Tashkent'
|
||||
| 'Asia/Calcutta'
|
||||
| 'Asia/Dhaka'
|
||||
| 'Asia/Almaty'
|
||||
| 'Asia/Jakarta'
|
||||
| 'Asia/Bangkok'
|
||||
| 'Asia/Shanghai'
|
||||
| 'Asia/Singapore'
|
||||
| 'Asia/Tokyo'
|
||||
| 'Asia/Seoul'
|
||||
| 'Australia/Brisbane'
|
||||
| 'Australia/Sydney'
|
||||
| 'Pacific/Guam'
|
||||
| 'Pacific/Noumea'
|
||||
| 'Pacific/Auckland'
|
||||
| 'Pacific/Fiji';
|
||||
|
||||
export interface Config {
|
||||
auth: {
|
||||
users: UserAuthOperations;
|
||||
};
|
||||
blocks: {};
|
||||
collections: {
|
||||
users: User;
|
||||
media: Media;
|
||||
project: Project;
|
||||
'payload-locked-documents': PayloadLockedDocument;
|
||||
'payload-preferences': PayloadPreference;
|
||||
'payload-migrations': PayloadMigration;
|
||||
};
|
||||
collectionsJoins: {};
|
||||
collectionsSelect: {
|
||||
users: UsersSelect<false> | UsersSelect<true>;
|
||||
media: MediaSelect<false> | MediaSelect<true>;
|
||||
project: ProjectSelect<false> | ProjectSelect<true>;
|
||||
'payload-locked-documents': PayloadLockedDocumentsSelect<false> | PayloadLockedDocumentsSelect<true>;
|
||||
'payload-preferences': PayloadPreferencesSelect<false> | PayloadPreferencesSelect<true>;
|
||||
'payload-migrations': PayloadMigrationsSelect<false> | PayloadMigrationsSelect<true>;
|
||||
};
|
||||
db: {
|
||||
defaultIDType: number;
|
||||
};
|
||||
globals: {
|
||||
home: Home;
|
||||
};
|
||||
globalsSelect: {
|
||||
home: HomeSelect<false> | HomeSelect<true>;
|
||||
};
|
||||
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;
|
||||
sessions?:
|
||||
| {
|
||||
id: string;
|
||||
createdAt?: string | null;
|
||||
expiresAt: 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;
|
||||
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;
|
||||
sizes?: {
|
||||
thumbnail?: {
|
||||
url?: string | null;
|
||||
width?: number | null;
|
||||
height?: number | null;
|
||||
mimeType?: string | null;
|
||||
filesize?: number | null;
|
||||
filename?: string | null;
|
||||
};
|
||||
};
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "project".
|
||||
*/
|
||||
export interface Project {
|
||||
id: number;
|
||||
title: string;
|
||||
description: string;
|
||||
featuredImage?: (number | null) | Media;
|
||||
tags?:
|
||||
| {
|
||||
tag: string;
|
||||
id?: string | null;
|
||||
}[]
|
||||
| null;
|
||||
viewLink?: string | null;
|
||||
repositoryLink?: string | null;
|
||||
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: 'project';
|
||||
value: number | Project;
|
||||
} | 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;
|
||||
sessions?:
|
||||
| T
|
||||
| {
|
||||
id?: T;
|
||||
createdAt?: T;
|
||||
expiresAt?: T;
|
||||
};
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "media_select".
|
||||
*/
|
||||
export interface MediaSelect<T extends boolean = true> {
|
||||
alt?: T;
|
||||
updatedAt?: T;
|
||||
createdAt?: T;
|
||||
url?: T;
|
||||
thumbnailURL?: T;
|
||||
filename?: T;
|
||||
mimeType?: T;
|
||||
filesize?: T;
|
||||
width?: T;
|
||||
height?: T;
|
||||
focalX?: T;
|
||||
focalY?: T;
|
||||
sizes?:
|
||||
| T
|
||||
| {
|
||||
thumbnail?:
|
||||
| T
|
||||
| {
|
||||
url?: T;
|
||||
width?: T;
|
||||
height?: T;
|
||||
mimeType?: T;
|
||||
filesize?: T;
|
||||
filename?: T;
|
||||
};
|
||||
};
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "project_select".
|
||||
*/
|
||||
export interface ProjectSelect<T extends boolean = true> {
|
||||
title?: T;
|
||||
description?: T;
|
||||
featuredImage?: T;
|
||||
tags?:
|
||||
| T
|
||||
| {
|
||||
tag?: T;
|
||||
id?: T;
|
||||
};
|
||||
viewLink?: T;
|
||||
repositoryLink?: 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` "home".
|
||||
*/
|
||||
export interface Home {
|
||||
id: number;
|
||||
mainLinks: {
|
||||
title: string;
|
||||
url: string;
|
||||
icon: 'code-2' | 'notebook' | 'github' | 'linkedin';
|
||||
id?: string | null;
|
||||
}[];
|
||||
popoverLinks: {
|
||||
title: string;
|
||||
url: string;
|
||||
icon: 'code-2' | 'notebook' | 'github' | 'linkedin';
|
||||
id?: string | null;
|
||||
}[];
|
||||
updatedAt?: string | null;
|
||||
createdAt?: string | null;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "home_select".
|
||||
*/
|
||||
export interface HomeSelect<T extends boolean = true> {
|
||||
mainLinks?:
|
||||
| T
|
||||
| {
|
||||
title?: T;
|
||||
url?: T;
|
||||
icon?: T;
|
||||
id?: T;
|
||||
};
|
||||
popoverLinks?:
|
||||
| T
|
||||
| {
|
||||
title?: T;
|
||||
url?: T;
|
||||
icon?: T;
|
||||
id?: T;
|
||||
};
|
||||
updatedAt?: T;
|
||||
createdAt?: T;
|
||||
globalType?: 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 {}
|
||||
}
|
||||
39
src/payload.config.ts
Normal file
39
src/payload.config.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
import { lexicalEditor } from '@payloadcms/richtext-lexical'
|
||||
import path from 'path'
|
||||
import { buildConfig } from 'payload'
|
||||
import { fileURLToPath } from 'url'
|
||||
import sharp from 'sharp'
|
||||
import { sqliteAdapter } from '@payloadcms/db-sqlite'
|
||||
|
||||
import { Users } from './collections/Users'
|
||||
import { Media } from './collections/Media'
|
||||
import { Projects } from "./collections/Projects"
|
||||
import { Home } from './globals/home'
|
||||
|
||||
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, Projects],
|
||||
globals: [Home],
|
||||
editor: lexicalEditor(),
|
||||
secret: process.env.PAYLOAD_SECRET || '',
|
||||
typescript: {
|
||||
outputFile: path.resolve(dirname, 'payload-types.ts'),
|
||||
},
|
||||
/**
|
||||
* Both our media and db will reside in the 'portfolio-data' directory
|
||||
* We can use a docker volume to persist this data
|
||||
*/
|
||||
db: sqliteAdapter({
|
||||
client: { url: "file:./portfolio-data/data.db" }
|
||||
}),
|
||||
sharp,
|
||||
plugins: [],
|
||||
})
|
||||
9
src/services/home-service.ts
Normal file
9
src/services/home-service.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import { getPayload } from 'payload'
|
||||
import config from '@payload-config'
|
||||
|
||||
export const getHome = async () => {
|
||||
const payload = await getPayload({ config })
|
||||
return await payload.findGlobal({
|
||||
slug: "home"
|
||||
})
|
||||
}
|
||||
9
src/services/projects-service.ts
Normal file
9
src/services/projects-service.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import { getPayload } from 'payload'
|
||||
import config from '@payload-config'
|
||||
|
||||
export const getProjects = async () => {
|
||||
const payload = await getPayload({ config })
|
||||
return await payload.find({
|
||||
collection: "project"
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user