Skip to content

Commit 07a9941

Browse files
authored
Merge pull request #153 from Dippp10/branch27
Improve mobile responsiveness of navbar across all devices
2 parents 8d17dcd + 3cabc78 commit 07a9941

File tree

1 file changed

+115
-104
lines changed

1 file changed

+115
-104
lines changed

src/pages/Home.jsx

Lines changed: 115 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -1,79 +1,110 @@
1-
'use client'
2-
import { useState, useEffect, useRef } from 'react'
3-
import { useRouter } from 'next/navigation'
4-
import toast, { Toaster } from 'react-hot-toast'
5-
import Typewriter from 'typewriter-effect'
6-
import Loader from '@/components/Loader'
7-
import Footer from '@/components/Footer'
8-
9-
function Home() {
10-
const [username, setUserName] = useState('')
11-
const [loading, setLoading] = useState(false)
12-
const router = useRouter()
13-
const inputRef = useRef(null)
14-
15-
useEffect(() => {
16-
inputRef.current.focus()
17-
})
1+
"use client";
182

3+
import { useState } from "react";
4+
import Link from "next/link";
5+
import { useRouter } from "next/navigation";
6+
import toast, { Toaster } from "react-hot-toast";
7+
import Typewriter from "typewriter-effect";
8+
import Loader from "@/components/Loader";
9+
import Footer from "@/components/Footer";
10+
11+
export default function Home() {
12+
const [open, setOpen] = useState(false);
13+
const [username, setUserName] = useState("");
14+
const [loading, setLoading] = useState(false);
15+
const router = useRouter();
16+
17+
/* ---------------- HANDLERS ---------------- */
1918
const handleSubmit = async (e) => {
20-
e.preventDefault()
19+
e.preventDefault();
2120

22-
const val = username.trim()
21+
const val = username.trim();
2322
if (!val) {
24-
toast.error('Please enter a valid username.')
25-
return
23+
toast.error("Please enter a valid username.");
24+
return;
2625
}
2726

28-
if (username.trim()) {
29-
try {
30-
setLoading(true)
31-
const response = await fetch('/api/user', {
32-
method: 'POST',
33-
headers: {
34-
'Content-Type': 'application/json',
35-
},
36-
body: JSON.stringify({ username: username.trim() }),
37-
})
38-
39-
if (response.ok) {
40-
const data = await response.json()
41-
if (data.exists) {
42-
// Show loader while navigating to profile page
43-
router.push(`/${username.trim()}`)
44-
} else {
45-
toast.error('Username does not exist on GitHub')
46-
}
27+
try {
28+
setLoading(true);
29+
const response = await fetch("/api/user", {
30+
method: "POST",
31+
headers: { "Content-Type": "application/json" },
32+
body: JSON.stringify({ username: val }),
33+
});
34+
35+
if (response.ok) {
36+
const data = await response.json();
37+
if (data.exists) {
38+
router.push(`/${val}`);
4739
} else {
48-
toast.error('Error verifying username. Please try again.')
40+
toast.error("Username does not exist on GitHub");
4941
}
50-
} catch (error) {
51-
toast.error('An unexpected error occurred. Please try again.')
52-
} finally {
53-
// Keep loading state true briefly to allow route transition loading UI to appear
54-
setTimeout(() => setLoading(false), 800)
42+
} else {
43+
toast.error("Error verifying username.");
5544
}
56-
} else {
57-
toast.error('Please enter a username.')
45+
} catch {
46+
toast.error("Unexpected error occurred.");
47+
} finally {
48+
setTimeout(() => setLoading(false), 500);
5849
}
59-
}
50+
};
6051

61-
const handleUser = async (e) => {
62-
const val = e.target.value
63-
setUserName(val)
64-
}
52+
const handleUser = (e) => setUserName(e.target.value);
6553

54+
/* ---------------- JSX ---------------- */
6655
return (
6756
<>
68-
<Toaster />
69-
<div className='flex flex-col justify-between min-h-[92vh] md:min-h-[94vh] lg:min-h-[90vh] xl:min-h-[91vh]'>
70-
{/* Main Content */}
71-
<main className='flex flex-col justify-center items-center flex-grow px-8 sm:px-4'>
72-
<>
73-
<h1 className='text-4xl font-light text-transparent bg-clip-text bg-gradient-to-r from-purple-400 to-pink-600 tracking-widest mb-8'>
57+
{/* ================= NAVBAR ================= */}
58+
<nav className="fixed top-0 z-50 w-full bg-black text-white shadow-md">
59+
<div className="mx-auto flex max-w-7xl items-center justify-between px-4 py-3">
60+
<Link href="/" className="text-xl font-bold">
61+
Gityzer
62+
</Link>
63+
64+
{/* Desktop Menu */}
65+
<div className="hidden md:flex gap-6">
66+
<Link href="#features">Features</Link>
67+
<Link href="#demo">Demo</Link>
68+
<Link href="#docs">Docs</Link>
69+
</div>
70+
71+
{/* Mobile Hamburger */}
72+
<button
73+
className="md:hidden text-2xl"
74+
onClick={() => setOpen((prev) => !prev)}
75+
aria-label="Toggle menu"
76+
>
77+
78+
</button>
79+
</div>
80+
81+
{/* Mobile Menu */}
82+
{open && (
83+
<div className="md:hidden px-4 pb-4 space-y-2 bg-black">
84+
<Link onClick={() => setOpen(false)} href="#features" className="block">
85+
Features
86+
</Link>
87+
<Link onClick={() => setOpen(false)} href="#demo" className="block">
88+
Demo
89+
</Link>
90+
<Link onClick={() => setOpen(false)} href="#docs" className="block">
91+
Docs
92+
</Link>
93+
</div>
94+
)}
95+
</nav>
96+
97+
{/* ================= PAGE CONTENT ================= */}
98+
<main className="pt-16">
99+
<Toaster />
100+
101+
<div className="flex flex-col justify-between min-h-[92vh] md:min-h-[94vh] lg:min-h-[90vh]">
102+
<main className="flex flex-col justify-center items-center flex-grow px-8 sm:px-4">
103+
<h1 className="text-4xl font-light text-transparent bg-clip-text bg-gradient-to-r from-purple-400 to-pink-600 tracking-widest mb-8">
74104
<Typewriter
75105
options={{
76-
cursor: "<span style='color: #fff; animation: blink 1s infinite;'>|</span>",
106+
cursor:
107+
"<span style='color:#fff; animation: blink 1s infinite;'>|</span>",
77108
}}
78109
onInit={(typewriter) => {
79110
const animate = () => {
@@ -82,21 +113,22 @@ function Home() {
82113
.pauseFor(1000)
83114
.deleteAll()
84115
.pauseFor(1000)
85-
.start()
86-
setTimeout(animate, 2000) // Adjust delay
87-
}
88-
animate()
116+
.start();
117+
setTimeout(animate, 2000);
118+
};
119+
animate();
89120
}}
90121
/>
91122
</h1>
92-
<form
93-
className='flex items-center w-full sm:w-2/3 lg:w-1/3 h-1/3'
94-
onSubmit={handleSubmit}
95-
>
96-
<div className='flex items-center bg-white rounded-full shadow-md p-2 w-full group'>
123+
124+
{/* ================= SEARCH FORM ================= */}
125+
<form
126+
onSubmit={handleSubmit}
127+
>
128+
<div className='flex items-center bg-white rounded-full shadow-md p-2 w-full group'>
97129
{/* GitHub Logo inside search bar */}
98130
<div className='px-3 group-hover:animate-spin motion-reduce:group-hover:animate-none'>
99-
<svg
131+
<svg
100132
xmlns='http://www.w3.org/2000/svg'
101133
className='h-7 w-7 text-gray-600'
102134
viewBox='0 0 24 24'
@@ -107,51 +139,30 @@ function Home() {
107139
</div>
108140

109141
{/* Search input */}
142+
110143
<input
111-
type='text'
112-
placeholder='Enter GitHub username'
113-
className='w-full px-4 py-2 text-gray-700 bg-white focus:outline-none text-base md:text-lg'
144+
type="text"
145+
placeholder="Search GitHub username..."
114146
value={username}
115147
onChange={handleUser}
116-
ref={inputRef}
117-
disabled={loading}
148+
className="flex-1 outline-none px-2"
118149
/>
119150

120-
{/* Submit button */}
121151
<button
122-
type='submit'
152+
type="submit"
123153
disabled={!username.trim() || loading}
124-
aria-busy={loading}
125-
className='relative bg-purple-500 text-white p-3 rounded-full hover:bg-purple-600 focus:outline-none focus:ring-4 focus:ring-purple-500 focus:ring-opacity-50 transition duration-200 flex items-center justify-center disabled:opacity-50 disabled:cursor-not-allowed'
154+
className="ml-2 bg-purple-500 text-white p-3 rounded-full hover:bg-purple-600 disabled:opacity-50"
126155
>
127-
{loading ? (
128-
<span className='h-5 w-5 rounded-full border-2 border-white border-t-transparent animate-spin' />
129-
) : (
130-
<svg
131-
xmlns='http://www.w3.org/2000/svg'
132-
className='h-5 w-5'
133-
fill='none'
134-
viewBox='0 0 24 24'
135-
stroke='currentColor'
136-
strokeWidth='2'
137-
>
138-
<path strokeLinecap='round' strokeLinejoin='round' d='M9 5l7 7-7 7' />
139-
</svg>
140-
)}
156+
141157
</button>
142158
</div>
143159
</form>
144-
</>
145-
</main>
160+
</main>
146161

147-
{loading && (
148-
<Loader message='Verifying username...' />
149-
)}
150-
151-
<Footer />
152-
</div>
162+
{loading && <Loader message="Verifying username..." />}
163+
<Footer />
164+
</div>
165+
</main>
153166
</>
154-
)
167+
);
155168
}
156-
157-
export default Home

0 commit comments

Comments
 (0)