├── .eslintrc.json ├── .gitignore ├── README.md ├── jsconfig.json ├── next.config.js ├── package-lock.json ├── package.json ├── public ├── about.png ├── brands.png ├── contact.png ├── favicon.ico ├── hero.gif ├── menu.png └── noavatar.png └── src ├── app ├── (auth) │ ├── login │ │ ├── login.module.css │ │ └── page.jsx │ └── register │ │ ├── page.jsx │ │ └── register.module.css ├── about │ ├── about.module.css │ └── page.jsx ├── admin │ ├── admin.module.css │ └── page.jsx ├── api │ ├── auth │ │ └── [...nextauth] │ │ │ └── route.js │ └── blog │ │ ├── [slug] │ │ └── route.js │ │ └── route.js ├── blog │ ├── [slug] │ │ ├── page.jsx │ │ └── singlePost.module.css │ ├── blog.module.css │ └── page.jsx ├── contact │ ├── contact.module.css │ └── page.jsx ├── error.jsx ├── globals.css ├── home.module.css ├── layout.js ├── loading.jsx ├── navigationtest │ └── page.jsx ├── not-found.jsx ├── page.jsx └── serveractiontest │ └── page.jsx ├── components ├── adminPostForm │ ├── adminPostForm.jsx │ └── adminPostForm.module.css ├── adminPosts │ ├── adminPosts.jsx │ └── adminPosts.module.css ├── adminUserForm │ ├── adminUserForm.jsx │ └── adminUserForm.module.css ├── adminUsers │ ├── adminUsers.jsx │ └── adminUsers.module.css ├── clientSideProviderTest.jsx ├── footer │ ├── Footer.jsx │ └── footer.module.css ├── hydrationTest.jsx ├── loginForm │ ├── loginForm.jsx │ └── loginForm.module.css ├── navbar │ ├── Navbar.jsx │ ├── links │ │ ├── Links.jsx │ │ ├── links.module.css │ │ └── navLink │ │ │ ├── navLink.jsx │ │ │ └── navLink.module.css │ └── navbar.module.css ├── postCard │ ├── postCard.jsx │ └── postCard.module.css ├── postUser │ ├── postUser.jsx │ └── postUser.module.css └── registerForm │ ├── registerForm.jsx │ └── registerForm.module.css ├── lib ├── action.js ├── auth.config.js ├── auth.js ├── data.js ├── models.js └── utils.js └── middleware.js /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "eslint:recommended", 4 | "next/core-web-vitals" 5 | ], 6 | "rules": { 7 | "react/prop-types": "off", 8 | "no-unused-vars": "warn" 9 | } 10 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | .yarn/install-state.gz 8 | 9 | # testing 10 | /coverage 11 | 12 | # next.js 13 | /.next/ 14 | /out/ 15 | 16 | # production 17 | /build 18 | 19 | # misc 20 | .DS_Store 21 | *.pem 22 | 23 | # debug 24 | npm-debug.log* 25 | yarn-debug.log* 26 | yarn-error.log* 27 | 28 | # local env files 29 | .env*.local 30 | .env 31 | 32 | # vercel 33 | .vercel 34 | 35 | # typescript 36 | *.tsbuildinfo 37 | next-env.d.ts 38 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Getting Started 2 | 3 | First, install the dependencies: 4 | 5 | ```bash 6 | npm install 7 | # or 8 | yarn install 9 | # or 10 | pnpm install 11 | # or 12 | bun install 13 | ``` 14 | 15 | 16 | run the development server: 17 | 18 | ```bash 19 | npm run dev 20 | # or 21 | yarn dev 22 | # or 23 | pnpm dev 24 | # or 25 | bun dev 26 | ``` 27 | 28 | Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. 29 | -------------------------------------------------------------------------------- /jsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "paths": { 4 | "@/*": ["./src/*"] 5 | } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /next.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('next').NextConfig} */ 2 | const nextConfig = { 3 | images:{ 4 | remotePatterns:[ 5 | { 6 | protocol: 'https', 7 | hostname: "images.pexels.com" 8 | } 9 | ] 10 | } 11 | } 12 | 13 | module.exports = nextConfig 14 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "next14starter", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "dev": "next dev", 7 | "build": "next build", 8 | "start": "next start", 9 | "lint": "next lint" 10 | }, 11 | "dependencies": { 12 | "bcryptjs": "^2.4.3", 13 | "install": "^0.13.0", 14 | "mongoose": "^8.0.0", 15 | "next": "14.0.4", 16 | "next-auth": "^5.0.0-beta.3", 17 | "npm": "^10.2.5", 18 | "react": "^18", 19 | "react-dom": "^18" 20 | }, 21 | "devDependencies": { 22 | "eslint": "^8", 23 | "eslint-config-next": "14.0.4" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /public/about.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/safak/next14-tutorial/d8383e400365dae7e1eef218a7d776ed7897a0bb/public/about.png -------------------------------------------------------------------------------- /public/brands.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/safak/next14-tutorial/d8383e400365dae7e1eef218a7d776ed7897a0bb/public/brands.png -------------------------------------------------------------------------------- /public/contact.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/safak/next14-tutorial/d8383e400365dae7e1eef218a7d776ed7897a0bb/public/contact.png -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/safak/next14-tutorial/d8383e400365dae7e1eef218a7d776ed7897a0bb/public/favicon.ico -------------------------------------------------------------------------------- /public/hero.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/safak/next14-tutorial/d8383e400365dae7e1eef218a7d776ed7897a0bb/public/hero.gif -------------------------------------------------------------------------------- /public/menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/safak/next14-tutorial/d8383e400365dae7e1eef218a7d776ed7897a0bb/public/menu.png -------------------------------------------------------------------------------- /public/noavatar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/safak/next14-tutorial/d8383e400365dae7e1eef218a7d776ed7897a0bb/public/noavatar.png -------------------------------------------------------------------------------- /src/app/(auth)/login/login.module.css: -------------------------------------------------------------------------------- 1 | .container{ 2 | display: flex; 3 | align-items: center; 4 | justify-content: center; 5 | } 6 | 7 | .wrapper{ 8 | width: 500px; 9 | background-color: var(--bgSoft); 10 | padding: 50px; 11 | display: flex; 12 | flex-direction: column; 13 | text-align: center; 14 | gap: 30px; 15 | border-radius: 5px; 16 | } 17 | 18 | .github{ 19 | width: 100%; 20 | padding: 20px; 21 | cursor: pointer; 22 | background-color: #fff; 23 | color: #000; 24 | font-weight: bold; 25 | border: none; 26 | border-radius: 5px; 27 | } -------------------------------------------------------------------------------- /src/app/(auth)/login/page.jsx: -------------------------------------------------------------------------------- 1 | import LoginForm from "@/components/loginForm/loginForm"; 2 | import { handleGithubLogin } from "@/lib/action"; 3 | import styles from "./login.module.css"; 4 | 5 | const LoginPage = () => { 6 | 7 | return ( 8 |
9 |
10 |
11 | 12 |
13 | 14 |
15 |
16 | ); 17 | }; 18 | 19 | export default LoginPage; 20 | -------------------------------------------------------------------------------- /src/app/(auth)/register/page.jsx: -------------------------------------------------------------------------------- 1 | import styles from "./register.module.css"; 2 | import RegisterForm from "@/components/registerForm/registerForm"; 3 | 4 | const RegisterPage = () => { 5 | return ( 6 |
7 |
8 | 9 |
10 |
11 | ); 12 | }; 13 | 14 | export default RegisterPage; 15 | -------------------------------------------------------------------------------- /src/app/(auth)/register/register.module.css: -------------------------------------------------------------------------------- 1 | .container{ 2 | display: flex; 3 | align-items: center; 4 | justify-content: center; 5 | } 6 | 7 | .wrapper{ 8 | width: 500px; 9 | background-color: var(--bgSoft); 10 | padding: 50px; 11 | display: flex; 12 | flex-direction: column; 13 | text-align: center; 14 | gap: 30px; 15 | border-radius: 5px; 16 | } 17 | 18 | -------------------------------------------------------------------------------- /src/app/about/about.module.css: -------------------------------------------------------------------------------- 1 | .container { 2 | display: flex; 3 | gap: 100px; 4 | } 5 | 6 | .textContainer { 7 | flex: 1; 8 | display: flex; 9 | flex-direction: column; 10 | gap: 50px; 11 | } 12 | 13 | .subtitle{ 14 | color:var(--btn) 15 | } 16 | 17 | .title{ 18 | font-size: 54px; 19 | } 20 | 21 | .desc{ 22 | font-size: 20px; 23 | font-weight: 300; 24 | } 25 | 26 | .boxes{ 27 | display: flex; 28 | align-items: center; 29 | justify-content: space-between; 30 | } 31 | 32 | .box{ 33 | display: flex; 34 | flex-direction: column; 35 | gap: 10px; 36 | } 37 | 38 | .box h1{ 39 | color: var(--btn); 40 | } 41 | 42 | .imgContainer { 43 | flex: 1; 44 | position: relative; 45 | } 46 | 47 | .img{ 48 | object-fit: contain; 49 | } 50 | 51 | @media (max-width: 768px) { 52 | .container { 53 | flex-direction: column; 54 | text-align: center; 55 | } 56 | 57 | .boxes{ 58 | flex-direction: column; 59 | gap: 50px; 60 | } 61 | } -------------------------------------------------------------------------------- /src/app/about/page.jsx: -------------------------------------------------------------------------------- 1 | import Image from "next/image"; 2 | import styles from "./about.module.css"; 3 | 4 | export const metadata = { 5 | title: "About Page", 6 | description: "About description", 7 | }; 8 | 9 | 10 | const AboutPage = () => { 11 | 12 | // console.log("lets check where it works") 13 | return ( 14 |
15 |
16 |

About Agency

17 |

18 | We create digital ideas that are bigger, bolder, braver and better. 19 |

20 |

21 | We create digital ideas that are bigger, bolder, braver and better. We 22 | believe in good ideas flexibility and precission We’re world’s Our 23 | Special Team best consulting & finance solution provider. Wide range 24 | of web and software development services. 25 |

26 |
27 |
28 |

10 K+

29 |

Year of experience

30 |
31 |
32 |

10 K+

33 |

Year of experience

34 |
35 |
36 |

10 K+

37 |

Year of experience

38 |
39 |
40 |
41 |
42 | About Image 48 |
49 |
50 | ); 51 | }; 52 | 53 | export default AboutPage; 54 | -------------------------------------------------------------------------------- /src/app/admin/admin.module.css: -------------------------------------------------------------------------------- 1 | .container { 2 | margin-top: 50px; 3 | display: flex; 4 | flex-direction: column; 5 | gap: 100px; 6 | } 7 | 8 | .row { 9 | display: flex; 10 | gap: 100px; 11 | } 12 | 13 | .row h1{ 14 | font-size: 24px; 15 | font-weight: 300; 16 | } 17 | 18 | .col { 19 | flex: 1; 20 | } 21 | 22 | .col img { 23 | object-fit: cover; 24 | border-radius: 50%; 25 | } 26 | 27 | .line{ 28 | margin: 100px; 29 | color: var(--bgSoft) 30 | } 31 | 32 | @media (max-width: 768px) { 33 | .row { 34 | flex-direction: column; 35 | } 36 | } -------------------------------------------------------------------------------- /src/app/admin/page.jsx: -------------------------------------------------------------------------------- 1 | import { Suspense } from "react"; 2 | import styles from "./admin.module.css"; 3 | import AdminPosts from "@/components/adminPosts/adminPosts"; 4 | import AdminPostForm from "@/components/adminPostForm/adminPostForm"; 5 | import AdminUsers from "@/components/adminUsers/adminUsers"; 6 | import AdminUserForm from "@/components/adminUserForm/adminUserForm"; 7 | import { auth } from "@/lib/auth"; 8 | 9 | const AdminPage = async () => { 10 | 11 | const session = await auth(); 12 | 13 | return ( 14 |
15 |
16 |
17 | Loading...
}> 18 | 19 | 20 |
21 |
22 | 23 |
24 |
25 |
26 |
27 | Loading...
}> 28 | 29 | 30 |
31 |
32 | 33 |
34 | 35 | 36 | ); 37 | }; 38 | 39 | export default AdminPage; 40 | -------------------------------------------------------------------------------- /src/app/api/auth/[...nextauth]/route.js: -------------------------------------------------------------------------------- 1 | export { GET, POST } from "@/lib/auth" -------------------------------------------------------------------------------- /src/app/api/blog/[slug]/route.js: -------------------------------------------------------------------------------- 1 | import { Post } from "@/lib/models"; 2 | import { connectToDb } from "@/lib/utils"; 3 | import { NextResponse } from "next/server"; 4 | 5 | export const GET = async (request, { params }) => { 6 | const { slug } = params; 7 | 8 | try { 9 | connectToDb(); 10 | 11 | const post = await Post.findOne({ slug }); 12 | return NextResponse.json(post); 13 | } catch (err) { 14 | console.log(err); 15 | throw new Error("Failed to fetch post!"); 16 | } 17 | }; 18 | 19 | export const DELETE = async (request, { params }) => { 20 | const { slug } = params; 21 | 22 | try { 23 | connectToDb(); 24 | 25 | await Post.deleteOne({ slug }); 26 | return NextResponse.json("Post deleted"); 27 | } catch (err) { 28 | console.log(err); 29 | throw new Error("Failed to delete post!"); 30 | } 31 | }; 32 | -------------------------------------------------------------------------------- /src/app/api/blog/route.js: -------------------------------------------------------------------------------- 1 | import { Post } from "@/lib/models"; 2 | import { connectToDb } from "@/lib/utils"; 3 | import { NextResponse } from "next/server"; 4 | 5 | export const GET = async (request) => { 6 | try { 7 | connectToDb(); 8 | 9 | const posts = await Post.find(); 10 | return NextResponse.json(posts); 11 | } catch (err) { 12 | console.log(err); 13 | throw new Error("Failed to fetch posts!"); 14 | } 15 | }; 16 | -------------------------------------------------------------------------------- /src/app/blog/[slug]/page.jsx: -------------------------------------------------------------------------------- 1 | import Image from "next/image"; 2 | import styles from "./singlePost.module.css"; 3 | import PostUser from "@/components/postUser/postUser"; 4 | import { Suspense } from "react"; 5 | import { getPost } from "@/lib/data"; 6 | 7 | // FETCH DATA WITH AN API 8 | const getData = async (slug) => { 9 | const res = await fetch(`http://localhost:3000/api/blog/${slug}`); 10 | 11 | if (!res.ok) { 12 | throw new Error("Something went wrong"); 13 | } 14 | 15 | return res.json(); 16 | }; 17 | 18 | export const generateMetadata = async ({ params }) => { 19 | const { slug } = params; 20 | 21 | const post = await getPost(slug); 22 | 23 | return { 24 | title: post.title, 25 | description: post.desc, 26 | }; 27 | }; 28 | 29 | const SinglePostPage = async ({ params }) => { 30 | const { slug } = params; 31 | 32 | // FETCH DATA WITH AN API 33 | const post = await getData(slug); 34 | 35 | // FETCH DATA WITHOUT AN API 36 | // const post = await getPost(slug); 37 | 38 | return ( 39 |
40 | {post.img && ( 41 |
42 | 43 |
44 | )} 45 |
46 |

{post.title}

47 |
48 | {post && ( 49 | Loading...
}> 50 | 51 | 52 | )} 53 |
54 | Published 55 | 56 | {post.createdAt.toString().slice(4, 16)} 57 | 58 |
59 |
60 |
{post.desc}
61 |
62 | 63 | ); 64 | }; 65 | 66 | export default SinglePostPage; 67 | -------------------------------------------------------------------------------- /src/app/blog/[slug]/singlePost.module.css: -------------------------------------------------------------------------------- 1 | .container { 2 | display: flex; 3 | gap: 100px; 4 | } 5 | 6 | .imgContainer { 7 | flex: 1; 8 | position: relative; 9 | height: calc(100vh - 200px); 10 | } 11 | 12 | .img{ 13 | object-fit: cover; 14 | } 15 | 16 | .textContainer { 17 | flex: 2; 18 | display: flex; 19 | flex-direction: column; 20 | gap: 50px; 21 | } 22 | 23 | .title{ 24 | font-size: 64px; 25 | } 26 | 27 | .detail{ 28 | display: flex; 29 | gap: 20px; 30 | } 31 | 32 | .detailText{ 33 | display: flex; 34 | flex-direction: column; 35 | gap: 10px; 36 | } 37 | 38 | .detailTitle{ 39 | color: gray; 40 | font-weight: bold; 41 | } 42 | 43 | .detailValue{ 44 | font-weight: 500; 45 | } 46 | 47 | .content{ 48 | font-size: 20px; 49 | } 50 | 51 | @media (max-width:768px){ 52 | .imgContainer{ 53 | display: none; 54 | } 55 | } -------------------------------------------------------------------------------- /src/app/blog/blog.module.css: -------------------------------------------------------------------------------- 1 | .container { 2 | display: flex; 3 | flex-wrap: wrap; 4 | gap: 20px; 5 | } 6 | 7 | .post { 8 | width: 30%; 9 | } 10 | 11 | @media screen and (max-width: 1280px) { 12 | .post { 13 | width: 45%; 14 | } 15 | } 16 | 17 | @media screen and (max-width: 768px) { 18 | .post { 19 | width: 100%; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/app/blog/page.jsx: -------------------------------------------------------------------------------- 1 | import PostCard from "@/components/postCard/postCard"; 2 | import styles from "./blog.module.css"; 3 | import { getPosts } from "@/lib/data"; 4 | 5 | // FETCH DATA WITH AN API 6 | const getData = async () => { 7 | const res = await fetch("http://localhost:3000/api/blog", {next:{revalidate:3600}}); 8 | 9 | if (!res.ok) { 10 | throw new Error("Something went wrong"); 11 | } 12 | 13 | return res.json(); 14 | }; 15 | 16 | const BlogPage = async () => { 17 | 18 | // FETCH DATA WITH AN API 19 | const posts = await getData(); 20 | 21 | // FETCH DATA WITHOUT AN API 22 | // const posts = await getPosts(); 23 | 24 | return ( 25 |
26 | {posts.map((post) => ( 27 |
28 | 29 |
30 | ))} 31 |
32 | ); 33 | }; 34 | 35 | export default BlogPage; 36 | -------------------------------------------------------------------------------- /src/app/contact/contact.module.css: -------------------------------------------------------------------------------- 1 | .container { 2 | display: flex; 3 | align-items: center; 4 | gap: 100px; 5 | } 6 | 7 | .imgContainer { 8 | flex: 1; 9 | height: 500px; 10 | position: relative; 11 | } 12 | 13 | .img { 14 | object-fit: contain; 15 | } 16 | 17 | .formContainer { 18 | flex: 1; 19 | } 20 | 21 | .form { 22 | display: flex; 23 | flex-direction: column; 24 | gap: 20px; 25 | } 26 | 27 | .form input, 28 | .form textarea { 29 | padding: 20px; 30 | border-radius: 5px; 31 | border: none; 32 | outline: none; 33 | background-color: var(--bgSoft); 34 | color: var(--text); 35 | } 36 | 37 | .form button { 38 | padding: 20px; 39 | background-color: var(--btn); 40 | color: var(--text); 41 | font-weight: bold; 42 | border: none; 43 | border-radius: 5px; 44 | cursor: pointer; 45 | } 46 | 47 | @media (max-width: 768px) { 48 | .container { 49 | flex-direction: column; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/app/contact/page.jsx: -------------------------------------------------------------------------------- 1 | // "use client"; 2 | import Image from "next/image"; 3 | import styles from "./contact.module.css"; 4 | // import dynamic from "next/dynamic"; 5 | // import HydrationTest from "@/components/hydrationTest"; 6 | 7 | // const HydrationTestNoSSR = dynamic(()=>import("@/components/hydrationTest"), {ssr: false}) 8 | 9 | export const metadata = { 10 | title: "Contact Page", 11 | description: "Contact description", 12 | }; 13 | 14 | const ContactPage = () => { 15 | // const a = Math.random(); 16 | 17 | // console.log(a); 18 | 19 | return ( 20 |
21 |
22 | 23 |
24 |
25 | {/* */} 26 | {/*
{a}
*/} 27 |
28 | 29 | 30 | 31 | 38 | 39 |
40 |
41 |
42 | ); 43 | }; 44 | 45 | export default ContactPage; 46 | -------------------------------------------------------------------------------- /src/app/error.jsx: -------------------------------------------------------------------------------- 1 | "use client" 2 | 3 | const Error = () => { 4 | return ( 5 |
Error
6 | ) 7 | } 8 | 9 | export default Error -------------------------------------------------------------------------------- /src/app/globals.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --bg: #0d0c22; 3 | --bgSoft: #2d2b42; 4 | --text: white; 5 | --textSoft: #e5e5e5; 6 | --btn: #3673fd; 7 | } 8 | 9 | * { 10 | margin: 0; 11 | padding: 0; 12 | box-sizing: border-box; 13 | } 14 | 15 | body { 16 | background-color: var(--bg); 17 | color: var(--text); 18 | 19 | } 20 | 21 | a { 22 | text-decoration: none; 23 | color: inherit; 24 | } 25 | 26 | .container { 27 | width: 1536px; 28 | margin: auto; 29 | padding-left: 50px; 30 | padding-right: 50px; 31 | min-height: 100vh; 32 | display: flex; 33 | flex-direction: column; 34 | justify-content: space-between; 35 | } 36 | 37 | @media (max-width: 1536px) { 38 | .container { 39 | width: 1366px; 40 | } 41 | } 42 | 43 | @media (max-width: 1366px) { 44 | .container { 45 | width: 1280px; 46 | } 47 | } 48 | 49 | @media (max-width: 1280px) { 50 | .container { 51 | width: 1024px; 52 | padding-left: 20px; 53 | padding-right: 20px; 54 | } 55 | } 56 | 57 | @media (max-width: 1024px) { 58 | .container { 59 | width: 768px; 60 | } 61 | } 62 | 63 | @media (max-width: 768px) { 64 | .container { 65 | width: 640px; 66 | } 67 | } 68 | 69 | @media (max-width: 640px) { 70 | .container { 71 | width: 475px; 72 | } 73 | } 74 | @media (max-width: 475px) { 75 | .container { 76 | width: 380px; 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/app/home.module.css: -------------------------------------------------------------------------------- 1 | .container { 2 | display: flex; 3 | gap: 100px; 4 | } 5 | 6 | .textContainer { 7 | flex: 1; 8 | display: flex; 9 | flex-direction: column; 10 | gap: 50px; 11 | } 12 | 13 | .title{ 14 | font-size: 96px; 15 | } 16 | 17 | .desc{ 18 | font-size: 20px; 19 | } 20 | 21 | .buttons{ 22 | display: flex; 23 | gap: 20px; 24 | } 25 | 26 | .button{ 27 | padding: 20px; 28 | min-width: 120px; 29 | cursor: pointer; 30 | border: none; 31 | border-radius: 5px; 32 | } 33 | 34 | .button:first-child{ 35 | background-color: var(--btn); 36 | color: var(--text); 37 | } 38 | 39 | .brands{ 40 | width: 500px; 41 | height: 50px; 42 | position: relative; 43 | filter: grayscale(1); 44 | } 45 | 46 | .imgContainer { 47 | flex: 1; 48 | position: relative; 49 | } 50 | 51 | @media (max-width: 1024px) { 52 | .container { 53 | flex-direction: column; 54 | text-align: center; 55 | } 56 | 57 | .buttons{ 58 | justify-content: center; 59 | } 60 | } 61 | 62 | @media (max-width: 768px) { 63 | .title { 64 | font-size: 64px; 65 | } 66 | 67 | .brands{ 68 | width: 100%; 69 | } 70 | } 71 | 72 | -------------------------------------------------------------------------------- /src/app/layout.js: -------------------------------------------------------------------------------- 1 | import { Inter } from "next/font/google"; 2 | import "./globals.css"; 3 | import Navbar from "@/components/navbar/Navbar"; 4 | import Footer from "@/components/footer/Footer"; 5 | import ClientSideProviderTest from "@/components/clientSideProviderTest"; 6 | 7 | const inter = Inter({ subsets: ["latin"] }); 8 | 9 | export const metadata = { 10 | title: { 11 | default:"Next.js 14 Homepage", 12 | template:"%s | Next.js 14" 13 | }, 14 | description: "Next.js starter app description", 15 | }; 16 | 17 | export default function RootLayout({ children }) { 18 | return ( 19 | 20 | 21 | {/* */} 22 |
23 | 24 | {children} 25 |
27 | {/*
*/} 28 | 29 | 30 | ); 31 | } 32 | -------------------------------------------------------------------------------- /src/app/loading.jsx: -------------------------------------------------------------------------------- 1 | const Loading = () => { 2 | return ( 3 |
Loading
4 | ) 5 | } 6 | 7 | export default Loading -------------------------------------------------------------------------------- /src/app/navigationtest/page.jsx: -------------------------------------------------------------------------------- 1 | "use client" 2 | import Link from "next/link" 3 | import { usePathname, useRouter, useSearchParams } from "next/navigation" 4 | 5 | const NavigationTestPage = () => { 6 | 7 | // CLIENT SIDE NAVIGATION 8 | const router = useRouter() 9 | const pathname = usePathname() 10 | const searchParams = useSearchParams() 11 | 12 | const q = searchParams.get("q") 13 | 14 | console.log(q) 15 | 16 | const handleClick = ()=>{ 17 | console.log("clicked") 18 | router.forward() 19 | } 20 | 21 | return ( 22 |
23 | Click here 24 | 25 |
26 | ) 27 | } 28 | 29 | export default NavigationTestPage -------------------------------------------------------------------------------- /src/app/not-found.jsx: -------------------------------------------------------------------------------- 1 | import Link from "next/link" 2 | 3 | const NotFound = () => { 4 | return ( 5 |
6 |

Not Found

7 |

Sorry, the page you are looking for does not exist.

8 | Return Home 9 |
10 | ) 11 | } 12 | 13 | export default NotFound -------------------------------------------------------------------------------- /src/app/page.jsx: -------------------------------------------------------------------------------- 1 | import Image from "next/image"; 2 | import styles from "./home.module.css"; 3 | 4 | const Home = () => { 5 | return ( 6 |
7 |
8 |

Creative Thoughts Agency.

9 |

10 | Lorem, ipsum dolor sit amet consectetur adipisicing elit. Vero 11 | blanditiis adipisci minima reiciendis a autem assumenda dolore. 12 |

13 |
14 | 15 | 16 |
17 |
18 | 19 |
20 |
21 |
22 | 23 |
24 |
25 | ); 26 | }; 27 | 28 | export default Home; 29 | -------------------------------------------------------------------------------- /src/app/serveractiontest/page.jsx: -------------------------------------------------------------------------------- 1 | import { addPost, deletePost } from "@/lib/action" 2 | 3 | const ServerActionTestPage = () => { 4 | 5 | // const actionInComponent = async ()=>{ 6 | // "use server" 7 | // console.log("it works!") 8 | // } 9 | 10 | return ( 11 |
12 |
13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 |
21 | 22 | 23 |
24 |
25 | ) 26 | } 27 | 28 | export default ServerActionTestPage -------------------------------------------------------------------------------- /src/components/adminPostForm/adminPostForm.jsx: -------------------------------------------------------------------------------- 1 | "use client" 2 | 3 | import { addPost } from "@/lib/action"; 4 | import styles from "./adminPostForm.module.css"; 5 | import { useFormState } from "react-dom"; 6 | 7 | const AdminPostForm = ({userId}) => { 8 | const [state, formAction] = useFormState(addPost, undefined); 9 | 10 | return ( 11 |
12 |

Add New Post

13 | 14 | 15 | 16 | 17 |