v1.0 working #1

Merged
dominiknatter merged 6 commits from dev into main 2025-03-27 17:06:30 +00:00
13 changed files with 406 additions and 18 deletions
Showing only changes of commit c5c9cc37af - Show all commits

View File

@@ -19,10 +19,14 @@
"@payloadcms/next": "latest",
"@payloadcms/payload-cloud": "latest",
"@payloadcms/richtext-lexical": "latest",
"@radix-ui/react-slot": "^1.1.2",
"@tailwindcss/postcss": "^4.0.17",
"auth": "^1.2.3",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"cross-env": "^7.0.3",
"graphql": "^16.8.1",
"lucide-react": "^0.484.0",
"next": "15.2.3",
"next-auth": "5.0.0-beta.25",
"payload": "latest",
@@ -31,7 +35,9 @@
"react": "19.0.0",
"react-dom": "19.0.0",
"sharp": "0.32.6",
"tailwindcss": "^4.0.17"
"tailwind-merge": "^3.0.2",
"tailwindcss": "^4.0.17",
"tw-animate-css": "^1.2.4"
},
"devDependencies": {
"@eslint/eslintrc": "^3.2.0",

75
pnpm-lock.yaml generated
View File

@@ -20,18 +20,30 @@ importers:
'@payloadcms/richtext-lexical':
specifier: latest
version: 3.31.0(@faceless-ui/modal@3.0.0-beta.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@faceless-ui/scroll-info@2.0.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@payloadcms/next@3.31.0(@types/react@19.0.12)(graphql@16.10.0)(monaco-editor@0.52.2)(next@15.2.3(react-dom@19.0.0(react@19.0.0))(react@19.0.0)(sass@1.77.4))(payload@3.31.0(graphql@16.10.0)(typescript@5.7.3))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)(typescript@5.7.3))(@types/react@19.0.12)(monaco-editor@0.52.2)(next@15.2.3(react-dom@19.0.0(react@19.0.0))(react@19.0.0)(sass@1.77.4))(payload@3.31.0(graphql@16.10.0)(typescript@5.7.3))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)(typescript@5.7.3)(yjs@13.6.24)
'@radix-ui/react-slot':
specifier: ^1.1.2
version: 1.1.2(@types/react@19.0.12)(react@19.0.0)
'@tailwindcss/postcss':
specifier: ^4.0.17
version: 4.0.17
auth:
specifier: ^1.2.3
version: 1.2.3
class-variance-authority:
specifier: ^0.7.1
version: 0.7.1
clsx:
specifier: ^2.1.1
version: 2.1.1
cross-env:
specifier: ^7.0.3
version: 7.0.3
graphql:
specifier: ^16.8.1
version: 16.10.0
lucide-react:
specifier: ^0.484.0
version: 0.484.0(react@19.0.0)
next:
specifier: 15.2.3
version: 15.2.3(react-dom@19.0.0(react@19.0.0))(react@19.0.0)(sass@1.77.4)
@@ -56,9 +68,15 @@ importers:
sharp:
specifier: 0.32.6
version: 0.32.6
tailwind-merge:
specifier: ^3.0.2
version: 3.0.2
tailwindcss:
specifier: ^4.0.17
version: 4.0.17
tw-animate-css:
specifier: ^1.2.4
version: 1.2.4
devDependencies:
'@eslint/eslintrc':
specifier: ^3.2.0
@@ -1391,6 +1409,24 @@ packages:
react: ^19.0.0 || ^19.0.0-rc-65a56d0e-20241020
react-dom: ^19.0.0 || ^19.0.0-rc-65a56d0e-20241020
'@radix-ui/react-compose-refs@1.1.1':
resolution: {integrity: sha512-Y9VzoRDSJtgFMUCoiZBDVo084VQ5hfpXxVE+NgkdNsjiDBByiImMZKKhxMwCbdHvhlENG6a833CbFkOQvTricw==}
peerDependencies:
'@types/react': '*'
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
peerDependenciesMeta:
'@types/react':
optional: true
'@radix-ui/react-slot@1.1.2':
resolution: {integrity: sha512-YAKxaiGsSQJ38VzKH86/BPRC4rh+b1Jpa+JneA5LRE7skmLPNAyeG8kPJj/oo4STLvlrs8vkf/iYyc3A5stYCQ==}
peerDependencies:
'@types/react': '*'
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
peerDependenciesMeta:
'@types/react':
optional: true
'@rtsao/scc@1.1.0':
resolution: {integrity: sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==}
@@ -2151,6 +2187,9 @@ packages:
resolution: {integrity: sha512-cYY9mypksY8NRqgDB1XD1RiJL338v/551niynFTGkZOO2LHuB2OmOYxDIe/ttN9AHwrqdum1360G3ald0W9kCg==}
engines: {node: '>=8'}
class-variance-authority@0.7.1:
resolution: {integrity: sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==}
classnames@2.5.1:
resolution: {integrity: sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==}
@@ -3294,6 +3333,11 @@ packages:
resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==}
hasBin: true
lucide-react@0.484.0:
resolution: {integrity: sha512-oZy8coK9kZzvqhSgfbGkPtTgyjpBvs3ukLgDPv14dSOZtBtboryWF5o8i3qen7QbGg7JhiJBz5mK1p8YoMZTLQ==}
peerDependencies:
react: ^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0
math-intrinsics@1.1.0:
resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==}
engines: {node: '>= 0.4'}
@@ -4134,6 +4178,9 @@ packages:
tabbable@6.2.0:
resolution: {integrity: sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==}
tailwind-merge@3.0.2:
resolution: {integrity: sha512-l7z+OYZ7mu3DTqrL88RiKrKIqO3NcpEO8V/Od04bNpvk0kiIFndGEoqfuzvj4yuhRkHKjRkII2z+KS2HfPcSxw==}
tailwindcss@4.0.17:
resolution: {integrity: sha512-OErSiGzRa6rLiOvaipsDZvLMSpsBZ4ysB4f0VKGXUrjw2jfkJRd6kjRKV2+ZmTCNvwtvgdDam5D7w6WXsdLJZw==}
@@ -4222,6 +4269,9 @@ packages:
tunnel-agent@0.6.0:
resolution: {integrity: sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==}
tw-animate-css@1.2.4:
resolution: {integrity: sha512-yt+HkJB41NAvOffe4NweJU6fLqAlVx/mBX6XmHRp15kq0JxTtOKaIw8pVSWM1Z+n2nXtyi7cW6C9f0WG/F/QAQ==}
type-check@0.4.0:
resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==}
engines: {node: '>= 0.8.0'}
@@ -6163,6 +6213,19 @@ snapshots:
- supports-color
- typescript
'@radix-ui/react-compose-refs@1.1.1(@types/react@19.0.12)(react@19.0.0)':
dependencies:
react: 19.0.0
optionalDependencies:
'@types/react': 19.0.12
'@radix-ui/react-slot@1.1.2(@types/react@19.0.12)(react@19.0.0)':
dependencies:
'@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.12)(react@19.0.0)
react: 19.0.0
optionalDependencies:
'@types/react': 19.0.12
'@rtsao/scc@1.1.0': {}
'@rushstack/eslint-patch@1.11.0': {}
@@ -7059,6 +7122,10 @@ snapshots:
ci-info@4.2.0: {}
class-variance-authority@0.7.1:
dependencies:
clsx: 2.1.1
classnames@2.5.1: {}
cli-cursor@5.0.0:
@@ -8265,6 +8332,10 @@ snapshots:
dependencies:
js-tokens: 4.0.0
lucide-react@0.484.0(react@19.0.0):
dependencies:
react: 19.0.0
math-intrinsics@1.1.0: {}
md5@2.3.0:
@@ -9374,6 +9445,8 @@ snapshots:
tabbable@6.2.0: {}
tailwind-merge@3.0.2: {}
tailwindcss@4.0.17: {}
tapable@2.2.1: {}
@@ -9481,6 +9554,8 @@ snapshots:
dependencies:
safe-buffer: 5.2.1
tw-animate-css@1.2.4: {}
type-check@0.4.0:
dependencies:
prelude-ls: 1.2.1

View File

@@ -0,0 +1,29 @@
"use client";
import { useState, useEffect } from 'react';
import { Input } from '@/components/ui/input';
export default function DiplomarbeitSearch() {
const [search, setSearch] = useState('');
const [results, setResults] = useState<string[]>([]);
useEffect(() => {
const timeoutId = setTimeout(async () => {
const response = await fetch(`/api/diplomarbeiten?search=${search}`);
const data = await response.json();
setResults(data.titles || []);
}, 500); // 500ms cooldown period
return () => clearTimeout(timeoutId);
}, [search]);
return (
<div className="w-full">
<Input type="text" value={search} placeholder="Suche" onChange={(e) => setSearch(e.target.value)} className="w-full" />
{results.map((title, index) => (
<div key={index}>
<h2>{title}</h2>
</div>
))}
</div>
);
}

View File

@@ -0,0 +1,15 @@
import React from 'react'
export default function Footer() {
return (
<footer className="w-full h-20 bg-htl-red flex flex-row items-center p-2 gap-4 shadow-lg justify-between">
<div className="w-auto flex items-center flex-row gap-4">
<p className="text-6xl text-white">HTL Dornbirn</p>
</div>
<div className="w-auto">
<p className="text-white">© 2021 HTL Dornbirn</p>
</div>
</footer>
)
}

View File

@@ -0,0 +1,27 @@
import Image from 'next/image'
import HTLDLogo from '@/app/(frontend)/htld.svg'
import { SignOutButton } from '@/app/(frontend)/_components/SignOutButton'
import { SignInButton } from '@/app/(frontend)/_components/SignInButton'
import React from 'react'
import { getPayloadSession } from 'payload-authjs'
export default async function Header(){
const session = await getPayloadSession();
return (
<header className="w-full h-20 bg-htl-red flex flex-row items-center p-2 gap-4 shadow-lg justify-between">
<div className="w-auto flex items-center flex-row gap-4">
<Image
className="h-16 w-auto"
src={HTLDLogo}
alt={"HTL Dornbirn Logo"}
/>
<p className="text-6xl text-white">Diplom- und Abschlussarbeiten</p>
</div>
<div className="w-auto">
{session ? <SignOutButton /> : <SignInButton />}
</div>
</header>
)
}

View File

@@ -1,4 +1,5 @@
import { signIn } from "@/auth";
import { Button } from '@/components/ui/button'
export function SignInButton() {
return (
@@ -8,7 +9,7 @@ export function SignInButton() {
await signIn("github");
}}
>
<button type="submit">Sign In</button>
<Button type="submit">Sign In</Button>
</form>
);
}

View File

@@ -1,6 +1,7 @@
"use client";
import type { CollectionSlug } from "payload";
import { Button } from '@/components/ui/button'
export function SignOutButton({
userCollectionSlug = "users",
@@ -8,7 +9,7 @@ export function SignOutButton({
userCollectionSlug?: CollectionSlug;
}) {
return (
<button
<Button
type="button"
onClick={async () => {
await fetch(`/api/${userCollectionSlug}/logout`, {
@@ -21,6 +22,6 @@ export function SignOutButton({
}}
>
Sign Out
</button>
</Button>
);
}

View File

@@ -1 +1,124 @@
@import "tailwindcss";
@import "tw-animate-css";
@theme {
--color-htl-red: #e4534dff;
}
@custom-variant dark (&:is(.dark *));
:root {
--radius: 0.625rem;
--background: oklch(1 0 0);
--foreground: oklch(0.145 0 0);
--card: oklch(1 0 0);
--card-foreground: oklch(0.145 0 0);
--popover: oklch(1 0 0);
--popover-foreground: oklch(0.145 0 0);
--primary: oklch(0.205 0 0);
--primary-foreground: oklch(0.985 0 0);
--secondary: oklch(0.97 0 0);
--secondary-foreground: oklch(0.205 0 0);
--muted: oklch(0.97 0 0);
--muted-foreground: oklch(0.556 0 0);
--accent: oklch(0.97 0 0);
--accent-foreground: oklch(0.205 0 0);
--destructive: oklch(0.577 0.245 27.325);
--border: oklch(0.922 0 0);
--input: oklch(0.922 0 0);
--ring: oklch(0.708 0 0);
--chart-1: oklch(0.646 0.222 41.116);
--chart-2: oklch(0.6 0.118 184.704);
--chart-3: oklch(0.398 0.07 227.392);
--chart-4: oklch(0.828 0.189 84.429);
--chart-5: oklch(0.769 0.188 70.08);
--sidebar: oklch(0.985 0 0);
--sidebar-foreground: oklch(0.145 0 0);
--sidebar-primary: oklch(0.205 0 0);
--sidebar-primary-foreground: oklch(0.985 0 0);
--sidebar-accent: oklch(0.97 0 0);
--sidebar-accent-foreground: oklch(0.205 0 0);
--sidebar-border: oklch(0.922 0 0);
--sidebar-ring: oklch(0.708 0 0);
}
.dark {
--background: oklch(0.145 0 0);
--foreground: oklch(0.985 0 0);
--card: oklch(0.205 0 0);
--card-foreground: oklch(0.985 0 0);
--popover: oklch(0.205 0 0);
--popover-foreground: oklch(0.985 0 0);
--primary: oklch(0.922 0 0);
--primary-foreground: oklch(0.205 0 0);
--secondary: oklch(0.269 0 0);
--secondary-foreground: oklch(0.985 0 0);
--muted: oklch(0.269 0 0);
--muted-foreground: oklch(0.708 0 0);
--accent: oklch(0.269 0 0);
--accent-foreground: oklch(0.985 0 0);
--destructive: oklch(0.704 0.191 22.216);
--border: oklch(1 0 0 / 10%);
--input: oklch(1 0 0 / 15%);
--ring: oklch(0.556 0 0);
--chart-1: oklch(0.488 0.243 264.376);
--chart-2: oklch(0.696 0.17 162.48);
--chart-3: oklch(0.769 0.188 70.08);
--chart-4: oklch(0.627 0.265 303.9);
--chart-5: oklch(0.645 0.246 16.439);
--sidebar: oklch(0.205 0 0);
--sidebar-foreground: oklch(0.985 0 0);
--sidebar-primary: oklch(0.488 0.243 264.376);
--sidebar-primary-foreground: oklch(0.985 0 0);
--sidebar-accent: oklch(0.269 0 0);
--sidebar-accent-foreground: oklch(0.985 0 0);
--sidebar-border: oklch(1 0 0 / 10%);
--sidebar-ring: oklch(0.556 0 0);
}
@theme inline {
--radius-sm: calc(var(--radius) - 4px);
--radius-md: calc(var(--radius) - 2px);
--radius-lg: var(--radius);
--radius-xl: calc(var(--radius) + 4px);
--color-background: var(--background);
--color-foreground: var(--foreground);
--color-card: var(--card);
--color-card-foreground: var(--card-foreground);
--color-popover: var(--popover);
--color-popover-foreground: var(--popover-foreground);
--color-primary: var(--primary);
--color-primary-foreground: var(--primary-foreground);
--color-secondary: var(--secondary);
--color-secondary-foreground: var(--secondary-foreground);
--color-muted: var(--muted);
--color-muted-foreground: var(--muted-foreground);
--color-accent: var(--accent);
--color-accent-foreground: var(--accent-foreground);
--color-destructive: var(--destructive);
--color-border: var(--border);
--color-input: var(--input);
--color-ring: var(--ring);
--color-chart-1: var(--chart-1);
--color-chart-2: var(--chart-2);
--color-chart-3: var(--chart-3);
--color-chart-4: var(--chart-4);
--color-chart-5: var(--chart-5);
--color-sidebar: var(--sidebar);
--color-sidebar-foreground: var(--sidebar-foreground);
--color-sidebar-primary: var(--sidebar-primary);
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
--color-sidebar-accent: var(--sidebar-accent);
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
--color-sidebar-border: var(--sidebar-border);
--color-sidebar-ring: var(--sidebar-ring);
}
@layer base {
* {
@apply border-border outline-ring/50;
}
body {
@apply bg-background text-foreground;
}
}

View File

@@ -0,0 +1,43 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 25.2.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Ebene_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 116.6 137.2" style="enable-background:new 0 0 116.6 137.2;" xml:space="preserve">
<style type="text/css">
.st0{fill:#FFFFFF;}
.st1{fill:#E4534D;}
.st2{fill:#3D4C5A;}
</style>
<g>
<g>
<path class="st0" d="M111.4,0H5.1C2.3,0,0,2.3,0,5.1v127c0,2.8,2.3,5.1,5.1,5.1h106.3c2.8,0,5.1-2.3,5.1-5.1V5.1
C116.6,2.3,114.2,0,111.4,0"/>
<path class="st1" d="M109.2,100.6c0,2.5-2,4.5-4.5,4.5H12c-2.5,0-4.5-2-4.5-4.5V11.7c0-2.5,2-4.5,4.5-4.5h92.8
c2.5,0,4.5,2,4.5,4.5V100.6z"/>
</g>
<polygon class="st0" points="26.8,81.3 20.3,81.3 20.3,70.1 15.1,70.1 15.1,97.5 20.3,97.5 20.3,85.9 26.8,85.9 26.8,97.5 32,97.5
32,70.1 26.8,70.1 "/>
<polygon class="st0" points="35.5,74.7 40.8,74.7 40.8,97.5 45.9,97.5 45.9,74.7 51.2,74.7 51.2,70.1 35.5,70.1 "/>
<polygon class="st0" points="59.9,70.1 54.8,70.1 54.8,97.5 68.9,97.5 68.9,92.8 59.9,92.8 "/>
<g>
<path class="st2" d="M69.1,126.3h-1.9v-5.1h1.8c2,0,2.9,0.8,2.9,2.6C71.8,125.4,70.8,126.3,69.1,126.3 M67.2,114.9h1.9
c1.5,0,2.3,0.6,2.3,1.9c0,1.2-0.8,1.9-2.2,1.9h-2V114.9z M72.6,120.2l-0.5-0.2l0.5-0.3c1.2-0.6,1.9-1.7,1.9-3
c0-2.7-2.1-4.4-5.4-4.4h-4.9v16.5h4.7c4,0,6.1-1.8,6.1-5.1C74.9,122.2,74.1,120.9,72.6,120.2"/>
<path class="st2" d="M27.2,126.3c-2,0-2.9-1.9-2.9-5.7c0-2.4,0.3-5.7,2.9-5.7c1.9,0,2.9,1.9,2.9,5.7
C30,124.5,29.1,126.3,27.2,126.3 M27.2,112.1c-3.8,0-6.1,3.2-6.1,8.5c0,5.4,2.2,8.5,6.1,8.5c3.8,0,6.1-3.2,6.1-8.5
C33.2,115.3,30.9,112.1,27.2,112.1"/>
<path class="st2" d="M41,119.9h-1.7v-4.8h1.6c1.9,0,2.9,0.8,2.9,2.4C43.7,118.6,43.2,119.9,41,119.9 M46.8,117.5
c0-3.2-2.1-5.1-5.8-5.1h-4.8v16.5h3.1v-6.3h1.2l2.9,6.3h3.4l-3.2-6.9l0.3-0.1C45.2,121.3,46.8,120,46.8,117.5"/>
<path class="st2" d="M57.7,119.2c0,0.7,0,1.7,0.1,2.5l0,0.3l0,1.3l-0.5-1.2c-0.3-0.8-0.8-1.8-1.1-2.5l-3.2-7.3h-3.2v16.5h2.8v-6.9
c0-0.7,0-1.8,0-2.8l0-1.2l0.5,1.1c0.4,1,0.8,2,1,2.4l3.4,7.4h3v-16.5h-2.8V119.2z"/>
<path class="st2" d="M89.6,119.9h-1.7v-4.8h1.6c1.9,0,2.9,0.8,2.9,2.4C92.3,118.6,91.8,119.9,89.6,119.9 M95.4,117.5
c0-3.2-2.1-5.1-5.8-5.1h-4.8v16.5h3.1v-6.3h1.3l2.9,6.3h3.4l-3.2-6.9l0.2-0.1C93.9,121.3,95.4,120,95.4,117.5"/>
<path class="st2" d="M106.3,112.4v6.8c0,0.7,0,1.8,0.1,2.7l0,0.2l0,1.2l-0.5-1.1c-0.3-0.8-0.8-1.8-1.1-2.5l-3.2-7.3h-3.2v16.5h2.8
v-6.9c0-0.8,0-1.8,0-2.8l0-1.3l0.5,1.2c0.4,1,0.8,2,1,2.4l3.4,7.4h3v-16.5H106.3z"/>
</g>
<rect x="77.9" y="112.4" class="st2" width="3.1" height="16.5"/>
<g>
<path class="st2" d="M11.7,126.2h-1v-11.1h1c2.6,0,3.8,1.8,3.8,5.6C15.5,124.5,14.4,126.2,11.7,126.2 M11.7,112.4H7.6v16.5h4
c3.2,0,7.1-1.4,7.1-8.3C18.7,115.2,16.4,112.4,11.7,112.4"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.8 KiB

View File

@@ -1,19 +1,23 @@
import React from 'react'
import './globals.css'
import React from "react";
import "./globals.css";
import Header from "@/app/(frontend)/_components/Header";
import Footer from "@/app/(frontend)/_components/Footer";
export const metadata = {
description: 'A blank template using Payload in a Next.js app.',
title: 'Payload Blank Template',
}
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
const { children } = props;
return (
<html lang="en">
<body>
<html lang="de-AT">
<body className="w-full min-h-full">
<Header />
<main>{children}</main>
<Footer />
</body>
</html>
)
);
}

View File

@@ -1,18 +1,39 @@
import { auth } from "@/auth";
import { getPayloadSession } from "payload-authjs";
import { SignInButton } from "./_components/SignInButton";
import { SignOutButton } from "./_components/SignOutButton";
import { getPayload } from 'payload'
import config from '@payload-config'
import { Input } from '@/components/ui/input'
import DiplomarbeitSearch from '@/app/(frontend)/_components/DiplomarbeitSearch'
const payload = await getPayload({ config })
const Page = async () => {
const authjsSession = await auth();
const payloadSession = await getPayloadSession();
const media = await payload.find({
collection: 'media',
})
return (
<main>
<div className="bg-red-500 bg-">
<h2 className="text-4xl">Mooongo Geiss</h2>
<div className="w-full flex justify-center pt-4">
<div className="w-1/3 flex flex-col items-center">
<h2 className="text-5xl w-auto ">Alle Diplomarbeiten</h2>
<DiplomarbeitSearch />
</div>
</div>
{payloadSession ? <SignOutButton /> : <SignInButton />}
{media.docs.map((med) => (
<div key={med.id}>
<h2>{med.url}</h2>
<p>{med.alt}</p>
</div>
))}
<br />
<h3>Auth.js Session</h3>
<pre>{JSON.stringify(authjsSession, null, 2)}</pre>

View File

@@ -0,0 +1,32 @@
import { NextRequest, NextResponse } from 'next/server';
import { getPayload } from 'payload';
import config from '@payload-config';
const payload = await getPayload({ config });
export async function GET(req: NextRequest) {
const searchParams = req.nextUrl.searchParams;
const search = searchParams.get('search');
if (!search) {
return NextResponse.json({ error: 'No documents matching search found' }, { status: 404 });
}
const response = await payload.find({
collection: 'papers',
where: {
or: [
{ title: { contains: search } },
{ issue: { contains: search } },
{ goal: { contains: search } },
{ 'technologies.description': { contains: search } },
{ 'prototype.description': { contains: search } },
{ 'authors.description': { contains: search } },
],
},
});
const titles = response.docs.map((doc) => doc.title);
return NextResponse.json({ titles });
}

View File

@@ -8,7 +8,18 @@ export const Papers: CollectionConfig = {
plural: 'Diplomarbeiten',
},
access: {
create: ({ req: { user } }) => {
return Boolean(user?.type == "admin") // <-- Check if the user is authenticated
},
delete: ({ req: { user } }) => {
return Boolean(user?.type == "admin") // <-- Check if the user is authenticated
},
update: async ({ req: { user }, id, findByID }) => {
if (user?.type == "admin") return true; // Admins can update any paper
const paper = await findByID({ collection: 'papers', id });
return paper.authors.some(author => author.user === user.id); // Check if the user is an author
},
},
admin: {
useAsTitle: 'title',