some progress
This commit is contained in:
parent
b1c2720d85
commit
4192a15779
@ -8,6 +8,6 @@ services:
|
|||||||
environment:
|
environment:
|
||||||
- POSTGRES_USER=postgres
|
- POSTGRES_USER=postgres
|
||||||
- POSTGRES_PASSWORD=admin
|
- POSTGRES_PASSWORD=admin
|
||||||
- POSTGRES_DB=prisma
|
- POSTGRES_DB=website
|
||||||
volumes:
|
volumes:
|
||||||
- ./pgdata:/var/lib/postgresql/data
|
- ./pgdata:/var/lib/postgresql/data
|
||||||
|
|||||||
@ -11,25 +11,29 @@
|
|||||||
},
|
},
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@heroicons/react": "^2.2.0",
|
||||||
"@payloadcms/db-postgres": "^3.31.0",
|
"@payloadcms/db-postgres": "^3.31.0",
|
||||||
"@payloadcms/next": "^3.31.0",
|
"@payloadcms/next": "^3.31.0",
|
||||||
"@payloadcms/richtext-lexical": "^3.31.0",
|
"@payloadcms/richtext-lexical": "^3.31.0",
|
||||||
"cross-env": "^7.0.3",
|
"cross-env": "^7.0.3",
|
||||||
"graphql": "^16.10.0",
|
"graphql": "^16.10.0",
|
||||||
|
"motion": "^12.6.5",
|
||||||
"next": "15.2.4",
|
"next": "15.2.4",
|
||||||
"payload": "^3.31.0",
|
"payload": "^3.31.0",
|
||||||
|
"postcss": "^8.5.3",
|
||||||
"react": "^19.0.0",
|
"react": "^19.0.0",
|
||||||
"react-dom": "^19.0.0",
|
"react-dom": "^19.0.0",
|
||||||
"sharp": "^0.33.5"
|
"sharp": "^0.33.5"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@tailwindcss/postcss": "^4",
|
"@tailwindcss/postcss": "^4.0.17",
|
||||||
"@tailwindcss/typography": "^0.5.16",
|
"@tailwindcss/typography": "^0.5.16",
|
||||||
"@types/node": "^20",
|
"@types/node": "^20",
|
||||||
"@types/react": "^19",
|
"@types/react": "^19",
|
||||||
"@types/react-dom": "^19",
|
"@types/react-dom": "^19",
|
||||||
|
"clsx": "^2.1.1",
|
||||||
"prettier": "^3.5.3",
|
"prettier": "^3.5.3",
|
||||||
"tailwindcss": "^4",
|
"tailwindcss": "^4.0.17",
|
||||||
"typescript": "^5"
|
"typescript": "^5"
|
||||||
},
|
},
|
||||||
"pnpm": {
|
"pnpm": {
|
||||||
|
|||||||
106
payload-types.ts
106
payload-types.ts
@ -93,10 +93,12 @@ export interface Config {
|
|||||||
defaultIDType: number;
|
defaultIDType: number;
|
||||||
};
|
};
|
||||||
globals: {
|
globals: {
|
||||||
home: Home;
|
homeHero: HomeHero;
|
||||||
|
homeProjects: HomeProject;
|
||||||
};
|
};
|
||||||
globalsSelect: {
|
globalsSelect: {
|
||||||
home: HomeSelect<false> | HomeSelect<true>;
|
homeHero: HomeHeroSelect<false> | HomeHeroSelect<true>;
|
||||||
|
homeProjects: HomeProjectsSelect<false> | HomeProjectsSelect<true>;
|
||||||
};
|
};
|
||||||
locale: null;
|
locale: null;
|
||||||
user: User & {
|
user: User & {
|
||||||
@ -549,33 +551,54 @@ export interface PayloadMigrationsSelect<T extends boolean = true> {
|
|||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* This interface was referenced by `Config`'s JSON-Schema
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
* via the `definition` "home".
|
* via the `definition` "homeHero".
|
||||||
*/
|
*/
|
||||||
export interface Home {
|
export interface HomeHero {
|
||||||
id: number;
|
id: number;
|
||||||
title?: string | null;
|
titleGroup: {
|
||||||
heroTitle?: string | null;
|
title: string;
|
||||||
heroDescription?: {
|
};
|
||||||
root: {
|
heroGroup: {
|
||||||
type: string;
|
heroTitle: string;
|
||||||
children: {
|
heroDescription: {
|
||||||
|
root: {
|
||||||
type: string;
|
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;
|
version: number;
|
||||||
[k: string]: unknown;
|
};
|
||||||
}[];
|
[k: string]: unknown;
|
||||||
direction: ('ltr' | 'rtl') | null;
|
|
||||||
format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | '';
|
|
||||||
indent: number;
|
|
||||||
version: number;
|
|
||||||
};
|
};
|
||||||
[k: string]: unknown;
|
heroItems?:
|
||||||
} | null;
|
| {
|
||||||
heroItems?:
|
name: string;
|
||||||
| {
|
id?: string | null;
|
||||||
name: string;
|
}[]
|
||||||
id?: string | null;
|
| null;
|
||||||
}[]
|
};
|
||||||
| null;
|
/**
|
||||||
|
* This title will be used for SEO purposes, and displayed in the browser tab.
|
||||||
|
*/
|
||||||
|
metaTitle: string;
|
||||||
|
/**
|
||||||
|
* This description will be used for SEO purposes (e.g., shown in search results and on social media cards).
|
||||||
|
*/
|
||||||
|
metaDescription: string;
|
||||||
|
updatedAt?: string | null;
|
||||||
|
createdAt?: string | null;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
|
* via the `definition` "homeProjects".
|
||||||
|
*/
|
||||||
|
export interface HomeProject {
|
||||||
|
id: number;
|
||||||
projectsTitle?: string | null;
|
projectsTitle?: string | null;
|
||||||
projectsDescription?: {
|
projectsDescription?: {
|
||||||
root: {
|
root: {
|
||||||
@ -597,18 +620,37 @@ export interface Home {
|
|||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* This interface was referenced by `Config`'s JSON-Schema
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
* via the `definition` "home_select".
|
* via the `definition` "homeHero_select".
|
||||||
*/
|
*/
|
||||||
export interface HomeSelect<T extends boolean = true> {
|
export interface HomeHeroSelect<T extends boolean = true> {
|
||||||
title?: T;
|
titleGroup?:
|
||||||
heroTitle?: T;
|
|
||||||
heroDescription?: T;
|
|
||||||
heroItems?:
|
|
||||||
| T
|
| T
|
||||||
| {
|
| {
|
||||||
name?: T;
|
title?: T;
|
||||||
id?: T;
|
|
||||||
};
|
};
|
||||||
|
heroGroup?:
|
||||||
|
| T
|
||||||
|
| {
|
||||||
|
heroTitle?: T;
|
||||||
|
heroDescription?: T;
|
||||||
|
heroItems?:
|
||||||
|
| T
|
||||||
|
| {
|
||||||
|
name?: T;
|
||||||
|
id?: T;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
metaTitle?: T;
|
||||||
|
metaDescription?: T;
|
||||||
|
updatedAt?: T;
|
||||||
|
createdAt?: T;
|
||||||
|
globalType?: T;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
|
* via the `definition` "homeProjects_select".
|
||||||
|
*/
|
||||||
|
export interface HomeProjectsSelect<T extends boolean = true> {
|
||||||
projectsTitle?: T;
|
projectsTitle?: T;
|
||||||
projectsDescription?: T;
|
projectsDescription?: T;
|
||||||
updatedAt?: T;
|
updatedAt?: T;
|
||||||
|
|||||||
@ -3,13 +3,14 @@ import { FixedToolbarFeature, lexicalEditor } from '@payloadcms/richtext-lexical
|
|||||||
import { postgresAdapter } from '@payloadcms/db-postgres'
|
import { postgresAdapter } from '@payloadcms/db-postgres'
|
||||||
import { buildConfig } from 'payload'
|
import { buildConfig } from 'payload'
|
||||||
|
|
||||||
import { Home } from '@/globals/Home'
|
import { HomeHero } from '@/globals/Home/Hero'
|
||||||
|
|
||||||
import { News } from './src/collections/News'
|
import { News } from './src/collections/News'
|
||||||
import { Projects } from '@/collections/Projects'
|
import { Projects } from '@/collections/Projects'
|
||||||
import { Images } from '@/collections/media/Images'
|
import { Images } from '@/collections/media/Images'
|
||||||
import { Documents } from '@/collections/media/Documents'
|
import { Documents } from '@/collections/media/Documents'
|
||||||
import { Data } from '@/collections/media/Data'
|
import { Data } from '@/collections/media/Data'
|
||||||
|
import { HomeProjects } from '@/globals/Home/Projects'
|
||||||
|
|
||||||
export default buildConfig({
|
export default buildConfig({
|
||||||
// If you'd like to use Rich Text, pass your editor here
|
// If you'd like to use Rich Text, pass your editor here
|
||||||
@ -22,7 +23,7 @@ export default buildConfig({
|
|||||||
|
|
||||||
serverURL: process.env.SERVER_URL || 'http://localhost:3000',
|
serverURL: process.env.SERVER_URL || 'http://localhost:3000',
|
||||||
|
|
||||||
globals: [Home],
|
globals: [HomeHero, HomeProjects],
|
||||||
|
|
||||||
// Define and configure your collections in this array
|
// Define and configure your collections in this array
|
||||||
collections: [Projects, News, Images, Documents, Data],
|
collections: [Projects, News, Images, Documents, Data],
|
||||||
|
|||||||
82
pnpm-lock.yaml
generated
82
pnpm-lock.yaml
generated
@ -8,6 +8,9 @@ importers:
|
|||||||
|
|
||||||
.:
|
.:
|
||||||
dependencies:
|
dependencies:
|
||||||
|
'@heroicons/react':
|
||||||
|
specifier: ^2.2.0
|
||||||
|
version: 2.2.0(react@19.0.0)
|
||||||
'@payloadcms/db-postgres':
|
'@payloadcms/db-postgres':
|
||||||
specifier: ^3.31.0
|
specifier: ^3.31.0
|
||||||
version: 3.31.0(@types/react@19.0.12)(payload@3.31.0(graphql@16.10.0)(typescript@5.8.2))(react@19.0.0)
|
version: 3.31.0(@types/react@19.0.12)(payload@3.31.0(graphql@16.10.0)(typescript@5.8.2))(react@19.0.0)
|
||||||
@ -23,12 +26,18 @@ importers:
|
|||||||
graphql:
|
graphql:
|
||||||
specifier: ^16.10.0
|
specifier: ^16.10.0
|
||||||
version: 16.10.0
|
version: 16.10.0
|
||||||
|
motion:
|
||||||
|
specifier: ^12.6.5
|
||||||
|
version: 12.6.5(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
|
||||||
next:
|
next:
|
||||||
specifier: 15.2.4
|
specifier: 15.2.4
|
||||||
version: 15.2.4(react-dom@19.0.0(react@19.0.0))(react@19.0.0)(sass@1.77.4)
|
version: 15.2.4(react-dom@19.0.0(react@19.0.0))(react@19.0.0)(sass@1.77.4)
|
||||||
payload:
|
payload:
|
||||||
specifier: ^3.31.0
|
specifier: ^3.31.0
|
||||||
version: 3.31.0(graphql@16.10.0)(typescript@5.8.2)
|
version: 3.31.0(graphql@16.10.0)(typescript@5.8.2)
|
||||||
|
postcss:
|
||||||
|
specifier: ^8.5.3
|
||||||
|
version: 8.5.3
|
||||||
react:
|
react:
|
||||||
specifier: ^19.0.0
|
specifier: ^19.0.0
|
||||||
version: 19.0.0
|
version: 19.0.0
|
||||||
@ -40,7 +49,7 @@ importers:
|
|||||||
version: 0.33.5
|
version: 0.33.5
|
||||||
devDependencies:
|
devDependencies:
|
||||||
'@tailwindcss/postcss':
|
'@tailwindcss/postcss':
|
||||||
specifier: ^4
|
specifier: ^4.0.17
|
||||||
version: 4.0.17
|
version: 4.0.17
|
||||||
'@tailwindcss/typography':
|
'@tailwindcss/typography':
|
||||||
specifier: ^0.5.16
|
specifier: ^0.5.16
|
||||||
@ -54,11 +63,14 @@ importers:
|
|||||||
'@types/react-dom':
|
'@types/react-dom':
|
||||||
specifier: ^19
|
specifier: ^19
|
||||||
version: 19.0.4(@types/react@19.0.12)
|
version: 19.0.4(@types/react@19.0.12)
|
||||||
|
clsx:
|
||||||
|
specifier: ^2.1.1
|
||||||
|
version: 2.1.1
|
||||||
prettier:
|
prettier:
|
||||||
specifier: ^3.5.3
|
specifier: ^3.5.3
|
||||||
version: 3.5.3
|
version: 3.5.3
|
||||||
tailwindcss:
|
tailwindcss:
|
||||||
specifier: ^4
|
specifier: ^4.0.17
|
||||||
version: 4.0.17
|
version: 4.0.17
|
||||||
typescript:
|
typescript:
|
||||||
specifier: ^5
|
specifier: ^5
|
||||||
@ -651,6 +663,11 @@ packages:
|
|||||||
'@floating-ui/utils@0.2.9':
|
'@floating-ui/utils@0.2.9':
|
||||||
resolution: {integrity: sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg==}
|
resolution: {integrity: sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg==}
|
||||||
|
|
||||||
|
'@heroicons/react@2.2.0':
|
||||||
|
resolution: {integrity: sha512-LMcepvRaS9LYHJGsF0zzmgKCUim/X3N/DQKc4jepAXJ7l8QxJ1PmxJzqplF2Z3FE4PqBAIGyJAQ/w4B5dsqbtQ==}
|
||||||
|
peerDependencies:
|
||||||
|
react: '>= 16 || ^19.0.0-rc'
|
||||||
|
|
||||||
'@img/sharp-darwin-arm64@0.33.5':
|
'@img/sharp-darwin-arm64@0.33.5':
|
||||||
resolution: {integrity: sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ==}
|
resolution: {integrity: sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ==}
|
||||||
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
|
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
|
||||||
@ -1482,6 +1499,20 @@ packages:
|
|||||||
focus-trap@7.5.4:
|
focus-trap@7.5.4:
|
||||||
resolution: {integrity: sha512-N7kHdlgsO/v+iD/dMoJKtsSqs5Dz/dXZVebRgJw23LDk+jMi/974zyiOYDziY2JPp8xivq9BmUGwIJMiuSBi7w==}
|
resolution: {integrity: sha512-N7kHdlgsO/v+iD/dMoJKtsSqs5Dz/dXZVebRgJw23LDk+jMi/974zyiOYDziY2JPp8xivq9BmUGwIJMiuSBi7w==}
|
||||||
|
|
||||||
|
framer-motion@12.6.5:
|
||||||
|
resolution: {integrity: sha512-MKvnWov0paNjvRJuIy6x418w23tFqRfS6CXHhZrCiSEpXVlo/F+usr8v4/3G6O0u7CpsaO1qop+v4Ip7PRCBqQ==}
|
||||||
|
peerDependencies:
|
||||||
|
'@emotion/is-prop-valid': '*'
|
||||||
|
react: ^18.0.0 || ^19.0.0
|
||||||
|
react-dom: ^18.0.0 || ^19.0.0
|
||||||
|
peerDependenciesMeta:
|
||||||
|
'@emotion/is-prop-valid':
|
||||||
|
optional: true
|
||||||
|
react:
|
||||||
|
optional: true
|
||||||
|
react-dom:
|
||||||
|
optional: true
|
||||||
|
|
||||||
fsevents@2.3.3:
|
fsevents@2.3.3:
|
||||||
resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
|
resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
|
||||||
engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
|
engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
|
||||||
@ -1837,6 +1868,26 @@ packages:
|
|||||||
monaco-editor@0.38.0:
|
monaco-editor@0.38.0:
|
||||||
resolution: {integrity: sha512-11Fkh6yzEmwx7O0YoLxeae0qEGFwmyPRlVxpg7oF9czOOCB/iCjdJrG5I67da5WiXK3YJCxoz9TJFE8Tfq/v9A==}
|
resolution: {integrity: sha512-11Fkh6yzEmwx7O0YoLxeae0qEGFwmyPRlVxpg7oF9czOOCB/iCjdJrG5I67da5WiXK3YJCxoz9TJFE8Tfq/v9A==}
|
||||||
|
|
||||||
|
motion-dom@12.6.5:
|
||||||
|
resolution: {integrity: sha512-jpM9TQLXzYMWMJ7Ec7sAj0iis8oIuu6WvjI3yNKJLdrZyrsI/b2cRInDVL8dCl683zQQq19DpL9cSMP+k8T1NA==}
|
||||||
|
|
||||||
|
motion-utils@12.6.5:
|
||||||
|
resolution: {integrity: sha512-IsOeKsOF+FWBhxQEDFBO6ZYC8/jlidmVbbLpe9/lXSA9j9kzGIMUuIBx2SZY+0reAS0DjZZ1i7dJp4NHrjocPw==}
|
||||||
|
|
||||||
|
motion@12.6.5:
|
||||||
|
resolution: {integrity: sha512-X3IIy76nxyk4I87xQEm5Ah8ojQ4qisd+/H592eXF14ha+xqpbDJcWOSf9PEKCOCC0K4PN/0UBaz+MvSQUkIeXQ==}
|
||||||
|
peerDependencies:
|
||||||
|
'@emotion/is-prop-valid': '*'
|
||||||
|
react: ^18.0.0 || ^19.0.0
|
||||||
|
react-dom: ^18.0.0 || ^19.0.0
|
||||||
|
peerDependenciesMeta:
|
||||||
|
'@emotion/is-prop-valid':
|
||||||
|
optional: true
|
||||||
|
react:
|
||||||
|
optional: true
|
||||||
|
react-dom:
|
||||||
|
optional: true
|
||||||
|
|
||||||
ms@2.1.3:
|
ms@2.1.3:
|
||||||
resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
|
resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
|
||||||
|
|
||||||
@ -2855,6 +2906,10 @@ snapshots:
|
|||||||
|
|
||||||
'@floating-ui/utils@0.2.9': {}
|
'@floating-ui/utils@0.2.9': {}
|
||||||
|
|
||||||
|
'@heroicons/react@2.2.0(react@19.0.0)':
|
||||||
|
dependencies:
|
||||||
|
react: 19.0.0
|
||||||
|
|
||||||
'@img/sharp-darwin-arm64@0.33.5':
|
'@img/sharp-darwin-arm64@0.33.5':
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
'@img/sharp-libvips-darwin-arm64': 1.0.4
|
'@img/sharp-libvips-darwin-arm64': 1.0.4
|
||||||
@ -3796,6 +3851,15 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
tabbable: 6.2.0
|
tabbable: 6.2.0
|
||||||
|
|
||||||
|
framer-motion@12.6.5(react-dom@19.0.0(react@19.0.0))(react@19.0.0):
|
||||||
|
dependencies:
|
||||||
|
motion-dom: 12.6.5
|
||||||
|
motion-utils: 12.6.5
|
||||||
|
tslib: 2.8.1
|
||||||
|
optionalDependencies:
|
||||||
|
react: 19.0.0
|
||||||
|
react-dom: 19.0.0(react@19.0.0)
|
||||||
|
|
||||||
fsevents@2.3.3:
|
fsevents@2.3.3:
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
@ -4229,6 +4293,20 @@ snapshots:
|
|||||||
|
|
||||||
monaco-editor@0.38.0: {}
|
monaco-editor@0.38.0: {}
|
||||||
|
|
||||||
|
motion-dom@12.6.5:
|
||||||
|
dependencies:
|
||||||
|
motion-utils: 12.6.5
|
||||||
|
|
||||||
|
motion-utils@12.6.5: {}
|
||||||
|
|
||||||
|
motion@12.6.5(react-dom@19.0.0(react@19.0.0))(react@19.0.0):
|
||||||
|
dependencies:
|
||||||
|
framer-motion: 12.6.5(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
|
||||||
|
tslib: 2.8.1
|
||||||
|
optionalDependencies:
|
||||||
|
react: 19.0.0
|
||||||
|
react-dom: 19.0.0(react@19.0.0)
|
||||||
|
|
||||||
ms@2.1.3: {}
|
ms@2.1.3: {}
|
||||||
|
|
||||||
nanoid@3.3.11: {}
|
nanoid@3.3.11: {}
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
const config = {
|
const config = {
|
||||||
plugins: ["@tailwindcss/postcss"],
|
plugins: { "@tailwindcss/postcss": {} },
|
||||||
};
|
};
|
||||||
|
|
||||||
export default config;
|
export default config;
|
||||||
|
|||||||
@ -1 +0,0 @@
|
|||||||
<svg fill="none" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M14.5 13.5V5.41a1 1 0 0 0-.3-.7L9.8.29A1 1 0 0 0 9.08 0H1.5v13.5A2.5 2.5 0 0 0 4 16h8a2.5 2.5 0 0 0 2.5-2.5m-1.5 0v-7H8v-5H3v12a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1M9.5 5V2.12L12.38 5zM5.13 5h-.62v1.25h2.12V5zm-.62 3h7.12v1.25H4.5zm.62 3h-.62v1.25h7.12V11z" clip-rule="evenodd" fill="#666" fill-rule="evenodd"/></svg>
|
|
||||||
|
Before Width: | Height: | Size: 391 B |
@ -1 +0,0 @@
|
|||||||
<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><g clip-path="url(#a)"><path fill-rule="evenodd" clip-rule="evenodd" d="M10.27 14.1a6.5 6.5 0 0 0 3.67-3.45q-1.24.21-2.7.34-.31 1.83-.97 3.1M8 16A8 8 0 1 0 8 0a8 8 0 0 0 0 16m.48-1.52a7 7 0 0 1-.96 0H7.5a4 4 0 0 1-.84-1.32q-.38-.89-.63-2.08a40 40 0 0 0 3.92 0q-.25 1.2-.63 2.08a4 4 0 0 1-.84 1.31zm2.94-4.76q1.66-.15 2.95-.43a7 7 0 0 0 0-2.58q-1.3-.27-2.95-.43a18 18 0 0 1 0 3.44m-1.27-3.54a17 17 0 0 1 0 3.64 39 39 0 0 1-4.3 0 17 17 0 0 1 0-3.64 39 39 0 0 1 4.3 0m1.1-1.17q1.45.13 2.69.34a6.5 6.5 0 0 0-3.67-3.44q.65 1.26.98 3.1M8.48 1.5l.01.02q.41.37.84 1.31.38.89.63 2.08a40 40 0 0 0-3.92 0q.25-1.2.63-2.08a4 4 0 0 1 .85-1.32 7 7 0 0 1 .96 0m-2.75.4a6.5 6.5 0 0 0-3.67 3.44 29 29 0 0 1 2.7-.34q.31-1.83.97-3.1M4.58 6.28q-1.66.16-2.95.43a7 7 0 0 0 0 2.58q1.3.27 2.95.43a18 18 0 0 1 0-3.44m.17 4.71q-1.45-.12-2.69-.34a6.5 6.5 0 0 0 3.67 3.44q-.65-1.27-.98-3.1" fill="#666"/></g><defs><clipPath id="a"><path fill="#fff" d="M0 0h16v16H0z"/></clipPath></defs></svg>
|
|
||||||
|
Before Width: | Height: | Size: 1.0 KiB |
BIN
public/ial-white-transp.png
Normal file
BIN
public/ial-white-transp.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 29 KiB |
@ -1 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 394 80"><path fill="#000" d="M262 0h68.5v12.7h-27.2v66.6h-13.6V12.7H262V0ZM149 0v12.7H94v20.4h44.3v12.6H94v21h55v12.6H80.5V0h68.7zm34.3 0h-17.8l63.8 79.4h17.9l-32-39.7 32-39.6h-17.9l-23 28.6-23-28.6zm18.3 56.7-9-11-27.1 33.7h17.8l18.3-22.7z"/><path fill="#000" d="M81 79.3 17 0H0v79.3h13.6V17l50.2 62.3H81Zm252.6-.4c-1 0-1.8-.4-2.5-1s-1.1-1.6-1.1-2.6.3-1.8 1-2.5 1.6-1 2.6-1 1.8.3 2.5 1a3.4 3.4 0 0 1 .6 4.3 3.7 3.7 0 0 1-3 1.8zm23.2-33.5h6v23.3c0 2.1-.4 4-1.3 5.5a9.1 9.1 0 0 1-3.8 3.5c-1.6.8-3.5 1.3-5.7 1.3-2 0-3.7-.4-5.3-1s-2.8-1.8-3.7-3.2c-.9-1.3-1.4-3-1.4-5h6c.1.8.3 1.6.7 2.2s1 1.2 1.6 1.5c.7.4 1.5.5 2.4.5 1 0 1.8-.2 2.4-.6a4 4 0 0 0 1.6-1.8c.3-.8.5-1.8.5-3V45.5zm30.9 9.1a4.4 4.4 0 0 0-2-3.3 7.5 7.5 0 0 0-4.3-1.1c-1.3 0-2.4.2-3.3.5-.9.4-1.6 1-2 1.6a3.5 3.5 0 0 0-.3 4c.3.5.7.9 1.3 1.2l1.8 1 2 .5 3.2.8c1.3.3 2.5.7 3.7 1.2a13 13 0 0 1 3.2 1.8 8.1 8.1 0 0 1 3 6.5c0 2-.5 3.7-1.5 5.1a10 10 0 0 1-4.4 3.5c-1.8.8-4.1 1.2-6.8 1.2-2.6 0-4.9-.4-6.8-1.2-2-.8-3.4-2-4.5-3.5a10 10 0 0 1-1.7-5.6h6a5 5 0 0 0 3.5 4.6c1 .4 2.2.6 3.4.6 1.3 0 2.5-.2 3.5-.6 1-.4 1.8-1 2.4-1.7a4 4 0 0 0 .8-2.4c0-.9-.2-1.6-.7-2.2a11 11 0 0 0-2.1-1.4l-3.2-1-3.8-1c-2.8-.7-5-1.7-6.6-3.2a7.2 7.2 0 0 1-2.4-5.7 8 8 0 0 1 1.7-5 10 10 0 0 1 4.3-3.5c2-.8 4-1.2 6.4-1.2 2.3 0 4.4.4 6.2 1.2 1.8.8 3.2 2 4.3 3.4 1 1.4 1.5 3 1.5 5h-5.8z"/></svg>
|
|
||||||
|
Before Width: | Height: | Size: 1.3 KiB |
@ -1 +0,0 @@
|
|||||||
<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1155 1000"><path d="m577.3 0 577.4 1000H0z" fill="#fff"/></svg>
|
|
||||||
|
Before Width: | Height: | Size: 128 B |
@ -1 +0,0 @@
|
|||||||
<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path fill-rule="evenodd" clip-rule="evenodd" d="M1.5 2.5h13v10a1 1 0 0 1-1 1h-11a1 1 0 0 1-1-1zM0 1h16v11.5a2.5 2.5 0 0 1-2.5 2.5h-11A2.5 2.5 0 0 1 0 12.5zm3.75 4.5a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5M7 4.75a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0m1.75.75a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5" fill="#666"/></svg>
|
|
||||||
|
Before Width: | Height: | Size: 385 B |
32
src/app/(frontend)/components/Header/Client.tsx
Normal file
32
src/app/(frontend)/components/Header/Client.tsx
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import clsx from "clsx";
|
||||||
|
import { motion } from "motion/react";
|
||||||
|
import React from "react";
|
||||||
|
|
||||||
|
export default function ClientHeader({
|
||||||
|
children,
|
||||||
|
}: {
|
||||||
|
children: React.ReactNode;
|
||||||
|
}) {
|
||||||
|
// const { scrollY } = useScroll();
|
||||||
|
// const [scrolled, setScrolled] = React.useState(0);
|
||||||
|
|
||||||
|
// const scrollPoint = window.innerHeight / 2;
|
||||||
|
|
||||||
|
// useMotionValueEvent(scrollY, "change", (latest) => {
|
||||||
|
// setScrolled(
|
||||||
|
// latest == 0 ? 0 : latest > scrollPoint ? 1 : latest / scrollPoint
|
||||||
|
// );
|
||||||
|
// });
|
||||||
|
|
||||||
|
return (
|
||||||
|
<motion.div
|
||||||
|
className={clsx(
|
||||||
|
"text-white absolute w-full top-0 z-50 bg-transparent lg:h-[var(--header-height)]"
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</motion.div>
|
||||||
|
);
|
||||||
|
}
|
||||||
10
src/app/(frontend)/components/Header/Header.tsx
Normal file
10
src/app/(frontend)/components/Header/Header.tsx
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
import ClientHeader from "./Client";
|
||||||
|
import ServerHeader from "./Server";
|
||||||
|
|
||||||
|
export default function Header() {
|
||||||
|
return (
|
||||||
|
<ClientHeader>
|
||||||
|
<ServerHeader />
|
||||||
|
</ClientHeader>
|
||||||
|
);
|
||||||
|
}
|
||||||
44
src/app/(frontend)/components/Header/Server.tsx
Normal file
44
src/app/(frontend)/components/Header/Server.tsx
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
// import SignIn from "@/components/sign-in";
|
||||||
|
// import SignOut from "@/components/sign-out";
|
||||||
|
import Image from "next/image";
|
||||||
|
|
||||||
|
import ialLogo from "../../../../../public/ial-white-transp.png";
|
||||||
|
import Link from "next/link";
|
||||||
|
import Button from "../ui/Button";
|
||||||
|
|
||||||
|
// import { auth } from "@/auth";
|
||||||
|
|
||||||
|
export default async function ServerHeader() {
|
||||||
|
// const session = await auth();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<nav className="flex h-full p-4 justify-between items-center container mx-auto">
|
||||||
|
{/* left */}
|
||||||
|
<div className="h-10 lg:h-20 relative w-20 lg:w-80">
|
||||||
|
<Image
|
||||||
|
src={ialLogo}
|
||||||
|
alt="iNZight Analytics Ltd"
|
||||||
|
className="h-full object-contain object-left"
|
||||||
|
fill
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* right */}
|
||||||
|
<div className="items-center gap-8 font-bold hidden lg:flex">
|
||||||
|
<Link href="/about">About</Link>
|
||||||
|
<Link href="/projects">Projects</Link>
|
||||||
|
<Link href="/news">News</Link>
|
||||||
|
<Link href="/apps">
|
||||||
|
<Button
|
||||||
|
type="primary"
|
||||||
|
variant="outlined"
|
||||||
|
className="border-white text-white hover:bg-white hover:text-black"
|
||||||
|
>
|
||||||
|
Apps
|
||||||
|
</Button>
|
||||||
|
</Link>
|
||||||
|
{/* {session ? <SignOut /> : <SignIn />} */}
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
);
|
||||||
|
}
|
||||||
22
src/app/(frontend)/components/home/CTA.tsx
Normal file
22
src/app/(frontend)/components/home/CTA.tsx
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
import { ChevronRightIcon } from "@heroicons/react/20/solid";
|
||||||
|
import Button from "../ui/Button";
|
||||||
|
|
||||||
|
export default function CTA() {
|
||||||
|
return (
|
||||||
|
<section className="bg-linear-to-tr from-accent-950 to-accent-700">
|
||||||
|
<div className="container px-4 lg:px-24 py-8 lg:py-48 mx-auto flex flex-col lg:flex-row justify-between items-start lg:items-center gap-4">
|
||||||
|
<h2 className="text-3xl lg:text-5xl leading-tight text-white font-medium">
|
||||||
|
Want to collaborate?
|
||||||
|
</h2>
|
||||||
|
<Button
|
||||||
|
className="lg:button-large border-white text-white hover:bg-white hover:text-accent-950 group"
|
||||||
|
type="alternate"
|
||||||
|
variant="outlined"
|
||||||
|
>
|
||||||
|
Get in touch
|
||||||
|
<ChevronRightIcon className="h-5 lg:h-10 w-5 lg:w-10 ml-2 group-hover:translate-x-2 transition" />
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
}
|
||||||
81
src/app/(frontend)/components/home/Hero.tsx
Normal file
81
src/app/(frontend)/components/home/Hero.tsx
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
import React from "react";
|
||||||
|
|
||||||
|
import configPromise from "@payload-config";
|
||||||
|
import { getPayload } from "payload";
|
||||||
|
|
||||||
|
import ScrollToSection from "./ScrollToSection";
|
||||||
|
import { RichText } from "@payloadcms/richtext-lexical/react";
|
||||||
|
|
||||||
|
export default async function Hero() {
|
||||||
|
const payload = await getPayload({ config: configPromise });
|
||||||
|
|
||||||
|
const hero = await payload.findGlobal({
|
||||||
|
slug: "homeHero",
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<section className="relative h-screen bg-black lg:pt-[var(--header-height)]">
|
||||||
|
hi
|
||||||
|
<div className="relative z-10 p-4 container mx-auto flex flex-col justify-end h-full pb-12 gap-8">
|
||||||
|
<h1 className="text-4xl lg:text-8xl lg:px-20 font-medium leading-tight text-white">
|
||||||
|
{hero.titleGroup.title}
|
||||||
|
</h1>
|
||||||
|
<div className="flex justify-center">
|
||||||
|
<ScrollToSection anchor="#about" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section
|
||||||
|
id="about"
|
||||||
|
className="h-screen overflow-clip bg-linear-to-b from:black to-accent-950 lg:bg-black"
|
||||||
|
>
|
||||||
|
<div className="px-4 py-8 lg:py-0 lg:px-24 h-full flex flex-col lg:flex-row container gap-16 lg:gap-32 lg:items-center justify-center mx-auto text-white">
|
||||||
|
<div className="flex flex-col lg:flex-1 gap-4 lg:gap-8 z-10">
|
||||||
|
<h2 className="text-3xl lg:text-5xl leading-tight">
|
||||||
|
{hero.heroGroup?.heroTitle}
|
||||||
|
</h2>
|
||||||
|
<div className="text-lg lg:text-2xl leading-tight">
|
||||||
|
<RichText data={hero.heroGroup.heroDescription} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="flex-1 lg:h-full flex lg:items-center lg:justify-center relative">
|
||||||
|
<div className="hidden lg:block h-[200%] bg-radial aspect-square absolute from-accent-900 to-black to-80%"></div>
|
||||||
|
<div className="hidden lg:block h-[100%] bg-radial aspect-square absolute from-white/10 to-transparent to-20%"></div>
|
||||||
|
<Oribal />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const Oribal = () => {
|
||||||
|
return (
|
||||||
|
<div className="lg:flex-1 lg:h-1/2 relative space-y-8">
|
||||||
|
<div className="hidden lg:block absolute h-full w-1/2 rounded-[100%] border-dashed border-white border rotate-10 left-1/2 -translate-x-1/2 translate-y-5"></div>
|
||||||
|
<div className="hidden lg:block absolute h-full w-1/2 rounded-[100%] border-dashed border-white border rotate-20 left-1/2 -translate-x-1/2"></div>
|
||||||
|
<div className="hidden lg:block absolute h-full w-1/2 rounded-[100%] border-dashed border-white border rotate-30 left-1/2 -translate-x-1/2 translate-y-10"></div>
|
||||||
|
|
||||||
|
<Planet text="Data design" className="right-2/5" />
|
||||||
|
<Planet text="Data collection" className="left-3/4 top-1/4" />
|
||||||
|
<Planet text="Data analysis" className="left-3/5 top-3/5" />
|
||||||
|
<Planet text="Data visualisation" className="left-2/7 top-full" />
|
||||||
|
<Planet text="Training" className="right-4/5 top-5/7" />
|
||||||
|
<Planet text="Data sovereignty" className="right-3/5 top-2/5" />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const Planet = ({ text, className }: { text: string; className?: string }) => {
|
||||||
|
return (
|
||||||
|
<div className={className}>
|
||||||
|
<span
|
||||||
|
className={`lg:absolute bg-accent-800/0 border border-white/10 backdrop-blur-md text-accent-100 font-bold px-6 shadow-lg py-2 rounded-full whitespace-nowrap ${className} hover:bg-accent-800`}
|
||||||
|
>
|
||||||
|
{text}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
59
src/app/(frontend)/components/home/News.tsx
Normal file
59
src/app/(frontend)/components/home/News.tsx
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
import Button from "@/components/ui/button";
|
||||||
|
import prisma from "@/lib/prisma";
|
||||||
|
import { ChevronRightIcon } from "@heroicons/react/20/solid";
|
||||||
|
import dayjs from "dayjs";
|
||||||
|
|
||||||
|
export default function News() {
|
||||||
|
return (
|
||||||
|
<section className="bg-secondary-50">
|
||||||
|
<div className="container px-4 lg:px-24 py-8 lg:py-48 mx-auto">
|
||||||
|
<div className="flex flex-col lg:flex-row justify-between items-start lg:items-center gap-4">
|
||||||
|
<h2 className="text-3xl lg:text-5xl leading-tight text-black">
|
||||||
|
We've got some news
|
||||||
|
</h2>
|
||||||
|
<Button type="primary" variant="outlined" className="group">
|
||||||
|
View all news
|
||||||
|
<ChevronRightIcon className="h-5 w-5 ml-2 group-hover:translate-x-1" />
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="py-12">
|
||||||
|
<Gallery />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function Gallery() {
|
||||||
|
const news = await prisma.news.findMany({
|
||||||
|
where: {
|
||||||
|
draft: false,
|
||||||
|
},
|
||||||
|
orderBy: {
|
||||||
|
date: "desc",
|
||||||
|
},
|
||||||
|
take: 3,
|
||||||
|
});
|
||||||
|
|
||||||
|
// TODO: parse markdown
|
||||||
|
return (
|
||||||
|
<div className="flex flex-col lg:grid lg:grid-cols-3 place-items-start gap-10 lg:gap-20">
|
||||||
|
{news.map((item) => (
|
||||||
|
<div key={item.id} className="space-y-2 lg:space-y-4">
|
||||||
|
<div className="text-sm text-accent-700">
|
||||||
|
{dayjs(item.date).format("DD/MM/YYYY")}
|
||||||
|
</div>
|
||||||
|
<h3 className="text-md lg:text-2xl text-black">{item.title}</h3>
|
||||||
|
<hr className="border-accent-800/20 hidden lg:block" />
|
||||||
|
<p className="text-gray-600 text-base leading-normal line-clamp-[10] hidden lg:block">
|
||||||
|
{item.body}
|
||||||
|
</p>
|
||||||
|
<Button type="alternate" variant="outlined">
|
||||||
|
Read more <ChevronRightIcon className="h-5 w-5 ml-2" />
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
54
src/app/(frontend)/components/home/Partners.tsx
Normal file
54
src/app/(frontend)/components/home/Partners.tsx
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import clsx from "clsx";
|
||||||
|
import { useState } from "react";
|
||||||
|
|
||||||
|
const PARTNERS = [
|
||||||
|
{ label: "Aotearoa", partners: [] },
|
||||||
|
{ label: "International", partners: [] },
|
||||||
|
];
|
||||||
|
|
||||||
|
export default function Partners() {
|
||||||
|
const [partner, setPartner] = useState(PARTNERS[0].label);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<section className="bg-gray-100">
|
||||||
|
<div className="container px-4 lg:px-24 py-8 lg:py-48 mx-auto lg:space-y-20">
|
||||||
|
<h2 className="text-3xl lg:text-5xl leading-tight text-black">
|
||||||
|
We've worked with …
|
||||||
|
</h2>
|
||||||
|
|
||||||
|
<div className="flex gap-6 lg:gap-20 flex-col lg:flex-row text-black">
|
||||||
|
<ul className="lg:border-t border-gray-500 lg:pr-8 pt-8 lg:space-y-4 flex lg:flex-col items-center lg:items-start gap-x-4">
|
||||||
|
{PARTNERS.map((group) => (
|
||||||
|
<li
|
||||||
|
key={group.label}
|
||||||
|
className={clsx(
|
||||||
|
"lg:space-y-4 text-xl lg:text-3xl flex items-center lg:gap-4 font-medium cursor-pointer",
|
||||||
|
group.label === partner && "text-accent-500"
|
||||||
|
)}
|
||||||
|
onClick={() => setPartner(group.label)}
|
||||||
|
>
|
||||||
|
{group.label}
|
||||||
|
<div
|
||||||
|
className={clsx(
|
||||||
|
"size-3 bg-accent-500 rounded-full hidden lg:block",
|
||||||
|
group.label !== partner && "opacity-0"
|
||||||
|
)}
|
||||||
|
></div>
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
<div className="pt-8 border-t border-gray-500 grid grid-cols-2 lg:grid-cols-4 gap-6 lg:gap-12 flex-1 justify-items-stretch">
|
||||||
|
{Array.from({ length: 12 }).map((_, index) => (
|
||||||
|
<div
|
||||||
|
key={index}
|
||||||
|
className="bg-gray-400/50 h-auto aspect-video rounded shadow"
|
||||||
|
></div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
}
|
||||||
79
src/app/(frontend)/components/home/Projects.tsx
Normal file
79
src/app/(frontend)/components/home/Projects.tsx
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
import Button from "@/components/ui/button";
|
||||||
|
import prisma from "@/lib/prisma";
|
||||||
|
import { ChevronRightIcon } from "@heroicons/react/20/solid";
|
||||||
|
import Image from "next/image";
|
||||||
|
|
||||||
|
export default function Projects() {
|
||||||
|
return (
|
||||||
|
<section className="bg-white text-black">
|
||||||
|
<div className="min-h-screen container px-4 lg:px-24 py-8 lg:py-48 mx-auto">
|
||||||
|
<div className="lg:w-3/5 space-y-8">
|
||||||
|
<h2 className="text-3xl lg:text-5xl leading-tight">
|
||||||
|
We do data differently
|
||||||
|
</h2>
|
||||||
|
|
||||||
|
<p className="text-lg lg:text-2xl leading-tight">
|
||||||
|
Lorem, ipsum dolor sit amet consectetur adipisicing elit. Commodi
|
||||||
|
modi repudiandae deleniti ut at, voluptatibus alias asperiores
|
||||||
|
temporibus sed id numquam nemo error ipsa adipisci perferendis.
|
||||||
|
Consequuntur vitae tenetur dolore.
|
||||||
|
</p>
|
||||||
|
<p className="text-lg lg:text-2xl leading-tight">
|
||||||
|
Eveniet doloremque ducimus deserunt labore, distinctio odit sunt
|
||||||
|
mollitia ab repellat excepturi aliquam fuga impedit! Maiores porro
|
||||||
|
qui consequatur nisi voluptates, odit facere nobis corrupti labore
|
||||||
|
ducimus cumque! Voluptates, beatae?
|
||||||
|
</p>
|
||||||
|
<Button type="primary" variant="outlined" className="group">
|
||||||
|
View all projects
|
||||||
|
<ChevronRightIcon className="h-5 w-5 ml-2 group-hover:translate-x-1" />
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="py-12">
|
||||||
|
<Gallery />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function Gallery() {
|
||||||
|
const projects = await prisma.project.findMany({
|
||||||
|
where: {
|
||||||
|
feature: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="flex flex-col gap-20">
|
||||||
|
{projects.map((project) => (
|
||||||
|
<div
|
||||||
|
key={project.id}
|
||||||
|
className="lg:w-3/5 py-8 lg:not-even:self-end space-y-8 border-b"
|
||||||
|
>
|
||||||
|
<div className="bg-gray-100 aspect-video relative shadow rounded overflow-clip">
|
||||||
|
{project.image && (
|
||||||
|
<Image
|
||||||
|
src={project.image}
|
||||||
|
alt={project.title}
|
||||||
|
fill={true}
|
||||||
|
className="object-cover"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-col lg:flex-row justify-between lg:items-center gap-4 items-start">
|
||||||
|
<h3 className="text-2xl lg:text-4xl text-accent-700">
|
||||||
|
{project.title}
|
||||||
|
</h3>
|
||||||
|
<Button type="alternate" variant="outlined" className="group">
|
||||||
|
View project{" "}
|
||||||
|
<ChevronRightIcon className="h-5 w-5 ml-2 transition group-hover:translate-x-1" />
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
<p className="text-gray-500 text-lg lg:text-2xl">{project.summary}</p>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
13
src/app/(frontend)/components/home/ScrollToSection.tsx
Normal file
13
src/app/(frontend)/components/home/ScrollToSection.tsx
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
"use client";
|
||||||
|
import { ArrowDownCircleIcon } from "@heroicons/react/20/solid";
|
||||||
|
|
||||||
|
export default function ScrollToSection({ anchor }: { anchor: string }) {
|
||||||
|
return (
|
||||||
|
<ArrowDownCircleIcon
|
||||||
|
className="h-10 text-white cursor-pointer opacity-20 hover:opacity-100"
|
||||||
|
onClick={() => {
|
||||||
|
document.querySelector(anchor)?.scrollIntoView({ behavior: "smooth" });
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
23
src/app/(frontend)/components/ui/Button.tsx
Normal file
23
src/app/(frontend)/components/ui/Button.tsx
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
export default function Button({
|
||||||
|
children,
|
||||||
|
type,
|
||||||
|
variant,
|
||||||
|
className,
|
||||||
|
...props
|
||||||
|
}: {
|
||||||
|
children: React.ReactNode;
|
||||||
|
type: "primary" | "secondary" | "alternate";
|
||||||
|
variant?: "filled" | "outlined";
|
||||||
|
className?: string;
|
||||||
|
// [x: string]:
|
||||||
|
}) {
|
||||||
|
const btnVariant = variant ?? "filled";
|
||||||
|
return (
|
||||||
|
<button
|
||||||
|
className={`button-${type} button-${btnVariant} transition whitespace-nowrap flex items-center ${className}`}
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</button>
|
||||||
|
);
|
||||||
|
}
|
||||||
@ -1,27 +0,0 @@
|
|||||||
@import "tailwindcss";
|
|
||||||
@plugin "@tailwindcss/typography";
|
|
||||||
|
|
||||||
:root {
|
|
||||||
--background: #ffffff;
|
|
||||||
--foreground: #171717;
|
|
||||||
}
|
|
||||||
|
|
||||||
@theme inline {
|
|
||||||
--color-background: var(--background);
|
|
||||||
--color-foreground: var(--foreground);
|
|
||||||
--font-sans: var(--font-geist-sans);
|
|
||||||
--font-mono: var(--font-geist-mono);
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (prefers-color-scheme: dark) {
|
|
||||||
:root {
|
|
||||||
--background: #0a0a0a;
|
|
||||||
--foreground: #ededed;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
body {
|
|
||||||
background: var(--background);
|
|
||||||
color: var(--foreground);
|
|
||||||
font-family: Arial, Helvetica, sans-serif;
|
|
||||||
}
|
|
||||||
@ -1,21 +1,30 @@
|
|||||||
import type { Metadata } from "next";
|
import type { Metadata } from "next";
|
||||||
import { Geist, Geist_Mono } from "next/font/google";
|
import configPromise from "@payload-config";
|
||||||
import "./globals.css";
|
import { getPayload } from "payload";
|
||||||
|
|
||||||
const geistSans = Geist({
|
import "../globals.css";
|
||||||
variable: "--font-geist-sans",
|
import Header from "./components/Header/Header";
|
||||||
|
|
||||||
|
import { Inter } from "next/font/google";
|
||||||
|
|
||||||
|
const inter = Inter({
|
||||||
subsets: ["latin"],
|
subsets: ["latin"],
|
||||||
|
display: "swap",
|
||||||
|
variable: "--font-inter",
|
||||||
});
|
});
|
||||||
|
|
||||||
const geistMono = Geist_Mono({
|
export async function generateMetadata(): Promise<Metadata> {
|
||||||
variable: "--font-geist-mono",
|
const payload = await getPayload({ config: configPromise });
|
||||||
subsets: ["latin"],
|
|
||||||
});
|
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
const homeHero = await payload.findGlobal({
|
||||||
title: "Create Next App",
|
slug: "homeHero",
|
||||||
description: "Generated by create next app",
|
});
|
||||||
};
|
|
||||||
|
return {
|
||||||
|
title: homeHero.metaTitle,
|
||||||
|
description: homeHero.metaDescription,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export default function RootLayout({
|
export default function RootLayout({
|
||||||
children,
|
children,
|
||||||
@ -24,10 +33,10 @@ export default function RootLayout({
|
|||||||
}>) {
|
}>) {
|
||||||
return (
|
return (
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<body
|
<body className={`${inter.variable} antialiased`}>
|
||||||
className={`${geistSans.variable} ${geistMono.variable} antialiased`}
|
<Header />
|
||||||
>
|
<div className="">{children}</div>
|
||||||
{children}
|
{/* <Footer /> */}
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -1,41 +1,11 @@
|
|||||||
import configPromise from "@payload-config";
|
import CTA from "./components/home/CTA";
|
||||||
import { RichText } from "@payloadcms/richtext-lexical/react";
|
import Hero from "./components/home/Hero";
|
||||||
import Link from "next/link";
|
|
||||||
import { getPayload } from "payload";
|
|
||||||
|
|
||||||
export default async function Page() {
|
export default async function Page() {
|
||||||
const payload = await getPayload({ config: configPromise });
|
|
||||||
|
|
||||||
const newsItems = await payload.find({
|
|
||||||
collection: "news",
|
|
||||||
depth: 1,
|
|
||||||
limit: 5,
|
|
||||||
select: {
|
|
||||||
title: true,
|
|
||||||
content: true,
|
|
||||||
},
|
|
||||||
sort: "-created_at",
|
|
||||||
});
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<>
|
||||||
<h1>My Homepage</h1>
|
<Hero />
|
||||||
<p>My Homepage content.</p>
|
<CTA />
|
||||||
|
</>
|
||||||
<h2>
|
|
||||||
<Link href="/news">Latest News</Link>
|
|
||||||
</h2>
|
|
||||||
<ul>
|
|
||||||
{newsItems.docs.map((newsItem) => (
|
|
||||||
<li key={newsItem.id} className="p-4">
|
|
||||||
<h3 className="text-2xl">{newsItem.title}</h3>
|
|
||||||
<RichText
|
|
||||||
data={newsItem.content}
|
|
||||||
className="prose bg-gray-50 p-2"
|
|
||||||
/>
|
|
||||||
</li>
|
|
||||||
))}
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
119
src/app/globals.css
Normal file
119
src/app/globals.css
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
@import "tailwindcss";
|
||||||
|
|
||||||
|
@theme {
|
||||||
|
--color-background: var(--background);
|
||||||
|
--color-foreground: var(--foreground);
|
||||||
|
|
||||||
|
--header-height: 175px;
|
||||||
|
|
||||||
|
--color-primary: var(--rojo);
|
||||||
|
|
||||||
|
--color-accent-50: #fff1f2;
|
||||||
|
--color-accent-100: #ffe1e3;
|
||||||
|
--color-accent-200: #ffc8cc;
|
||||||
|
--color-accent-300: #ffa1a8;
|
||||||
|
--color-accent-400: #fe6b76;
|
||||||
|
--color-accent-500: #f73c49;
|
||||||
|
--color-accent-600: #e52331;
|
||||||
|
--color-accent-700: #c01521;
|
||||||
|
--color-accent-800: #9f151f;
|
||||||
|
--color-accent-900: #841820;
|
||||||
|
--color-accent-950: #48070c;
|
||||||
|
|
||||||
|
--color-secondary-50: #f5f8f5;
|
||||||
|
--color-secondary-100: #e8f0e9;
|
||||||
|
--color-secondary-200: #d2e0d3;
|
||||||
|
--color-secondary-300: #aec7af;
|
||||||
|
--color-secondary-400: #82a684;
|
||||||
|
--color-secondary-500: #5f8862;
|
||||||
|
--color-secondary-600: #4b6e4d;
|
||||||
|
--color-secondary-700: #415d43;
|
||||||
|
--color-secondary-800: #344735;
|
||||||
|
--color-secondary-900: #2c3b2d;
|
||||||
|
--color-secondary-950: #141f16;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
The default border color has changed to `currentColor` in Tailwind CSS v4,
|
||||||
|
so we've added these compatibility styles to make sure everything still
|
||||||
|
looks the same as it did with Tailwind CSS v3.
|
||||||
|
|
||||||
|
If we ever want to remove these styles, we need to add an explicit border
|
||||||
|
color utility to any element that depends on these defaults.
|
||||||
|
*/
|
||||||
|
@layer base {
|
||||||
|
*,
|
||||||
|
::after,
|
||||||
|
::before,
|
||||||
|
::backdrop,
|
||||||
|
::file-selector-button {
|
||||||
|
border-color: var(--color-gray-200, currentColor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
:root {
|
||||||
|
--background: #ffffff;
|
||||||
|
--foreground: #171717;
|
||||||
|
|
||||||
|
/* https://coolors.co/000000-ffffff-e52331-709775-415d43 */
|
||||||
|
--black: #000000;
|
||||||
|
--white: #ffffff;
|
||||||
|
--rojo: #e52331;
|
||||||
|
--cambridge-blue: #709775;
|
||||||
|
--hunter-green: #415d43;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-color-scheme: dark) {
|
||||||
|
:root {
|
||||||
|
--background: #0a0a0a;
|
||||||
|
--foreground: #ededed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
color: var(--foreground);
|
||||||
|
background: var(--background);
|
||||||
|
font-family: var(--font-inter);
|
||||||
|
}
|
||||||
|
|
||||||
|
@utility button-default {
|
||||||
|
@apply font-bold py-2 px-4 rounded-sm cursor-pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
@layer components {
|
||||||
|
.button-primary {
|
||||||
|
@apply button-default;
|
||||||
|
}
|
||||||
|
.button-primary.button-filled {
|
||||||
|
@apply bg-accent-800 text-accent-100;
|
||||||
|
}
|
||||||
|
.button-primary.button-outlined {
|
||||||
|
@apply border border-accent-800 text-accent-800 hover:bg-accent-800 hover:text-accent-100;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-secondary {
|
||||||
|
@apply button-default;
|
||||||
|
/* bg-secondary-800 text-secondary-100 hover:bg-linear-to-tr hover:from-secondary-700 hover:to-secondary-800 hover:text-secondary-50; */
|
||||||
|
}
|
||||||
|
.button-secondary.button-filled {
|
||||||
|
@apply bg-secondary-800 text-secondary-100;
|
||||||
|
}
|
||||||
|
.button-secondary.button-outlined {
|
||||||
|
@apply border border-secondary-800 text-secondary-800 hover:bg-secondary-800 hover:text-secondary-100;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-alternate {
|
||||||
|
@apply button-default;
|
||||||
|
}
|
||||||
|
.button-alternate.button-filled {
|
||||||
|
@apply bg-black text-white;
|
||||||
|
}
|
||||||
|
.button-alternate.button-outlined {
|
||||||
|
@apply border border-black text-black hover:bg-black hover:text-white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-large {
|
||||||
|
@apply button-default;
|
||||||
|
@apply text-3xl px-8 py-4;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,51 +0,0 @@
|
|||||||
import { GlobalConfig } from "payload";
|
|
||||||
|
|
||||||
export const Home: GlobalConfig = {
|
|
||||||
slug: 'home',
|
|
||||||
fields: [
|
|
||||||
{
|
|
||||||
name: 'title',
|
|
||||||
label: 'Title',
|
|
||||||
type: 'text',
|
|
||||||
defaultValue: 'Analytics, research, and data visualisation that make a difference'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'heroTitle',
|
|
||||||
label: 'Hero Title',
|
|
||||||
type: 'text',
|
|
||||||
defaultValue: 'We help people tell stories with data'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'heroDescription',
|
|
||||||
label: 'Hero Description',
|
|
||||||
type: 'richText',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'heroItems',
|
|
||||||
label: 'Hero Items',
|
|
||||||
type: 'array',
|
|
||||||
fields: [
|
|
||||||
{
|
|
||||||
name: 'name',
|
|
||||||
label: 'Name',
|
|
||||||
type: 'text',
|
|
||||||
required: true,
|
|
||||||
}
|
|
||||||
],
|
|
||||||
defaultValue: ["Data design", "Data collection", "Data analysis", "Data visualisation", "Training", "Data sovereignty"].map((item) => ({
|
|
||||||
name: item,
|
|
||||||
})),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'projectsTitle',
|
|
||||||
label: 'Projects Title',
|
|
||||||
type: 'text',
|
|
||||||
defaultValue: 'We do data differently'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'projectsDescription',
|
|
||||||
label: 'Projects Description',
|
|
||||||
type: 'richText'
|
|
||||||
}
|
|
||||||
],
|
|
||||||
};
|
|
||||||
83
src/globals/Home/Hero.ts
Normal file
83
src/globals/Home/Hero.ts
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
import { GlobalConfig } from "payload";
|
||||||
|
|
||||||
|
export const HomeHero: GlobalConfig = {
|
||||||
|
slug: 'homeHero',
|
||||||
|
label: 'Hero',
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: 'titleGroup',
|
||||||
|
label: 'Landing page',
|
||||||
|
type: 'group',
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: 'title',
|
||||||
|
label: 'Title',
|
||||||
|
type: 'text',
|
||||||
|
required: true,
|
||||||
|
defaultValue: 'Analytics, research, and data visualisation that make a difference'
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'heroGroup',
|
||||||
|
label: 'Hero',
|
||||||
|
type: 'group',
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: 'heroTitle',
|
||||||
|
label: 'Hero Title',
|
||||||
|
type: 'text',
|
||||||
|
required: true,
|
||||||
|
defaultValue: 'We help people tell stories with data'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'heroDescription',
|
||||||
|
label: 'Hero Description',
|
||||||
|
type: 'richText',
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'heroItems',
|
||||||
|
label: 'Items',
|
||||||
|
type: 'array',
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: 'name',
|
||||||
|
label: 'Name',
|
||||||
|
type: 'text',
|
||||||
|
required: true,
|
||||||
|
}
|
||||||
|
],
|
||||||
|
defaultValue: ["Data design", "Data collection", "Data analysis", "Data visualisation", "Training", "Data sovereignty"].map((item) => ({
|
||||||
|
name: item,
|
||||||
|
})),
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'metaTitle',
|
||||||
|
label: 'Meta Title',
|
||||||
|
type: 'text',
|
||||||
|
defaultValue: 'iNZight Analytics Ltd',
|
||||||
|
required: true,
|
||||||
|
admin: {
|
||||||
|
position: 'sidebar',
|
||||||
|
description: 'This title will be used for SEO purposes, and displayed in the browser tab.',
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'metaDescription',
|
||||||
|
label: 'Meta Description',
|
||||||
|
type: 'textarea',
|
||||||
|
required: true,
|
||||||
|
defaultValue: 'iNZight Analytics Ltd is a New Zealand-based company that provides data analysis and visualisation services.',
|
||||||
|
admin: {
|
||||||
|
position: 'sidebar',
|
||||||
|
description: 'This description will be used for SEO purposes (e.g., shown in search results and on social media cards).',
|
||||||
|
}
|
||||||
|
},
|
||||||
|
],
|
||||||
|
admin: {
|
||||||
|
group: 'Home page'
|
||||||
|
}
|
||||||
|
};
|
||||||
22
src/globals/Home/Projects.ts
Normal file
22
src/globals/Home/Projects.ts
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
import { GlobalConfig } from "payload";
|
||||||
|
|
||||||
|
export const HomeProjects: GlobalConfig = {
|
||||||
|
slug: 'homeProjects',
|
||||||
|
label: 'Projects',
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: 'projectsTitle',
|
||||||
|
label: 'Projects Title',
|
||||||
|
type: 'text',
|
||||||
|
defaultValue: 'We do data differently'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'projectsDescription',
|
||||||
|
label: 'Projects Description',
|
||||||
|
type: 'richText'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
admin: {
|
||||||
|
group: 'Home page'
|
||||||
|
}
|
||||||
|
};
|
||||||
Loading…
x
Reference in New Issue
Block a user