Add components for home and login pages (#128)

* Run create-next-app

* Add READMEs

* Remove stuff we don't need

* Add dummy data

* Add types for dummy data

* Add dummy routes

* Remove unused CSS

* Split dummy data and definitions

* Add prettier plugin for tailwind

* Create background-blur.tsx

* Create hero.tsx

* Create login-form.tsx

* Tweak

* Fix ts error
This commit is contained in:
Delba de Oliveira
2023-08-30 16:47:42 +01:00
committed by GitHub
parent 8dd0d1d863
commit 4376abb821
9 changed files with 233 additions and 13 deletions

View File

@@ -16,7 +16,7 @@ export default function RootLayout({
}) {
return (
<html lang="en">
<body className={inter.className}>{children}</body>
<body className={`bg-white ${inter.className}`}>{children}</body>
</html>
)
}

View File

@@ -1,7 +1,9 @@
import LoginForm from "@/app/ui/login-form";
export default function Page() {
return (
<div>
<div>Replace with login-form.tsx</div>
</div>
)
<main>
<LoginForm />
</main>
);
}

View File

@@ -1,11 +1,9 @@
import Hero from "@/app/ui/hero";
export default function Page() {
return (
<div>
<div>
Landing page. Login button should be in content to avoid root layouts
and route groups complexity.
<button>Login</button>
</div>
</div>
)
<main>
<Hero />
</main>
);
}

View File

@@ -0,0 +1,8 @@
export default function BackgroundBlur() {
return (
<div className="-z-10">
<div className="absolute left-[55%] top-[10%] h-40 w-40 rounded-full bg-gradient-to-r from-blue-200 via-blue-300 to-blue-500 opacity-90 blur-3xl"></div>
<div className="absolute left-[50%] top-[18%] h-40 w-40 transform rounded-full bg-gradient-to-r from-blue-200 via-blue-300 to-blue-500 opacity-60 blur-3xl"></div>
</div>
);
}

View File

@@ -0,0 +1,30 @@
import BackgroundBlur from "@/app/ui/background-blur";
export default function Hero() {
return (
<>
<div className="mx-auto mt-20 flex flex-col items-center space-y-6 p-2 md:w-1/3">
<BackgroundBlur />
<h1 className="text-center text-4xl font-bold tracking-tight text-zinc-900 sm:text-5xl">
Next.js Dashboard
</h1>
<p className="text-center leading-6 text-zinc-900">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut vulputate
dapibus consectetur. Duis quis eros euismod.
</p>
<a href="/login">
<button className="rounded-md bg-black px-4 py-2 text-sm font-semibold text-white hover:bg-zinc-700">
Log in
</button>
</a>
</div>
<div className="mx-auto mt-12 w-full px-4 lg:w-2/3">
<img
src="https://vercel.com/_next/image?url=https%3A%2F%2Fassets.vercel.com%2Fimage%2Fupload%2Ffront%2Finsights%2Fanalytics_dashboard.png&w=3840&q=75&dpl=dpl_9Tp4gaAJ1QFc4eSRJ99UwWvWgZ73"
alt="Dashboard image"
/>
</div>
</>
);
}

View File

@@ -0,0 +1,71 @@
"use client";
import BackgroundBlur from "@/app/ui/background-blur";
import React, { useState } from "react";
// This component contains basic logic for a React Form.
// We'll be updating it in Chapter 8 - Adding Authentication.
export default function LoginForm() {
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const handleSubmit = (e: { preventDefault: () => void }) => {
e.preventDefault();
console.log(`Email: ${email}, Password: ${password}`);
};
return (
<div className="mt-40 flex h-screen flex-col items-center space-y-6">
<BackgroundBlur />
<a href="/">
<img className="h-6 w-auto" src="/logo.svg" alt="Next.js Logo" />
</a>
<p className="text-center font-semibold text-zinc-900">
Log in to your dashboard
</p>
<div className="w-full max-w-sm">
<form onSubmit={handleSubmit} className="px-4">
<div>
<label
className="block text-sm font-medium leading-8 text-zinc-900"
htmlFor="email"
>
Email
</label>
<input
className="block w-full rounded-md border-0 p-1.5 text-zinc-900 shadow-sm ring-1 ring-inset ring-zinc-300 sm:text-sm"
id="email"
type="text"
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
</div>
<div className="mt-4">
<label
className="block text-sm font-medium leading-8 text-zinc-900"
htmlFor="password"
>
Password
</label>
<input
className="block w-full rounded-md border-0 p-1.5 text-zinc-900 shadow-sm ring-1 ring-inset ring-zinc-300 sm:text-sm"
id="password"
type="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
/>
</div>
<div className="mt-6">
<button
className="w-full rounded-md bg-black px-4 py-2 text-center text-sm font-semibold text-white hover:bg-zinc-700"
type="submit"
>
Log in
</button>
</div>
</form>
</div>
</div>
);
}

View File

@@ -20,6 +20,10 @@
"react-dom": "18.2.0",
"tailwindcss": "3.3.3",
"typescript": "5.2.2"
},
"devDependencies": {
"prettier": "^3.0.3",
"prettier-plugin-tailwindcss": "^0.5.3"
}
},
"node_modules/@aashutoshrathi/word-wrap": {
@@ -3122,6 +3126,93 @@
"node": ">= 0.8.0"
}
},
"node_modules/prettier": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.0.3.tgz",
"integrity": "sha512-L/4pUDMxcNa8R/EthV08Zt42WBO4h1rarVtK0K+QJG0X187OLo7l699jWw0GKuwzkPQ//jMFA/8Xm6Fh3J/DAg==",
"dev": true,
"bin": {
"prettier": "bin/prettier.cjs"
},
"engines": {
"node": ">=14"
},
"funding": {
"url": "https://github.com/prettier/prettier?sponsor=1"
}
},
"node_modules/prettier-plugin-tailwindcss": {
"version": "0.5.3",
"resolved": "https://registry.npmjs.org/prettier-plugin-tailwindcss/-/prettier-plugin-tailwindcss-0.5.3.tgz",
"integrity": "sha512-M5K80V21yM+CTm/FEFYRv9/9LyInYbCSXpIoPAKMm8zy89IOwdiA2e4JVbcO7tvRtAQWz32zdj7/WKcsmFyAVg==",
"dev": true,
"engines": {
"node": ">=14.21.3"
},
"peerDependencies": {
"@ianvs/prettier-plugin-sort-imports": "*",
"@prettier/plugin-pug": "*",
"@shopify/prettier-plugin-liquid": "*",
"@shufo/prettier-plugin-blade": "*",
"@trivago/prettier-plugin-sort-imports": "*",
"prettier": "^3.0",
"prettier-plugin-astro": "*",
"prettier-plugin-css-order": "*",
"prettier-plugin-import-sort": "*",
"prettier-plugin-jsdoc": "*",
"prettier-plugin-organize-attributes": "*",
"prettier-plugin-organize-imports": "*",
"prettier-plugin-style-order": "*",
"prettier-plugin-svelte": "*"
},
"peerDependenciesMeta": {
"@ianvs/prettier-plugin-sort-imports": {
"optional": true
},
"@prettier/plugin-pug": {
"optional": true
},
"@shopify/prettier-plugin-liquid": {
"optional": true
},
"@shufo/prettier-plugin-blade": {
"optional": true
},
"@trivago/prettier-plugin-sort-imports": {
"optional": true
},
"prettier-plugin-astro": {
"optional": true
},
"prettier-plugin-css-order": {
"optional": true
},
"prettier-plugin-import-sort": {
"optional": true
},
"prettier-plugin-jsdoc": {
"optional": true
},
"prettier-plugin-marko": {
"optional": true
},
"prettier-plugin-organize-attributes": {
"optional": true
},
"prettier-plugin-organize-imports": {
"optional": true
},
"prettier-plugin-style-order": {
"optional": true
},
"prettier-plugin-svelte": {
"optional": true
},
"prettier-plugin-twig-melody": {
"optional": true
}
}
},
"node_modules/prop-types": {
"version": "15.8.1",
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
@@ -6111,6 +6202,19 @@
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
"integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g=="
},
"prettier": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.0.3.tgz",
"integrity": "sha512-L/4pUDMxcNa8R/EthV08Zt42WBO4h1rarVtK0K+QJG0X187OLo7l699jWw0GKuwzkPQ//jMFA/8Xm6Fh3J/DAg==",
"dev": true
},
"prettier-plugin-tailwindcss": {
"version": "0.5.3",
"resolved": "https://registry.npmjs.org/prettier-plugin-tailwindcss/-/prettier-plugin-tailwindcss-0.5.3.tgz",
"integrity": "sha512-M5K80V21yM+CTm/FEFYRv9/9LyInYbCSXpIoPAKMm8zy89IOwdiA2e4JVbcO7tvRtAQWz32zdj7/WKcsmFyAVg==",
"dev": true,
"requires": {}
},
"prop-types": {
"version": "15.8.1",
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",

View File

@@ -21,5 +21,9 @@
"react-dom": "18.2.0",
"tailwindcss": "3.3.3",
"typescript": "5.2.2"
},
"devDependencies": {
"prettier": "^3.0.3",
"prettier-plugin-tailwindcss": "^0.5.3"
}
}

View File

@@ -0,0 +1,3 @@
module.exports = {
plugins: ["prettier-plugin-tailwindcss"],
};