Skip to content

Commit

Permalink
Kukreja (#10)
Browse files Browse the repository at this point in the history
* Update home page UI and feat: Add an archive feature

* Edit URL validation logic to handle duplicates

* Add middleware for authentication

* Refactor Navbar color logic based on pathname

* Refactor Home component

* Improve error handling in signIn component and refactor name fields to use camelCase

* build error fix

---------

Co-authored-by: Prateek <[email protected]>
Co-authored-by: Prateek Rohilla <[email protected]>
  • Loading branch information
3 people authored Sep 25, 2024
1 parent 2981ad0 commit 2be4dd7
Show file tree
Hide file tree
Showing 8 changed files with 308 additions and 106 deletions.
6 changes: 3 additions & 3 deletions app/MobileNav.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,12 @@ export default function MobileNav() {
</Link>
<Link href="/about">
<span className="block pl-3 pr-4 py-2 border-l-4 border-transparent text-base font-medium text-gray-600 hover:text-gray-800 hover:bg-gray-50 hover:border-gray-300 cursor-pointer">
About
Archive
</span>
</Link>
<Link href="/contact">
<span className="block pl-3 pr-4 py-2 border-l-4 border-transparent text-base font-medium text-gray-600 hover:text-gray-800 hover:bg-gray-50 hover:border-gray-300 cursor-pointer">
Contact
Profile
</span>
</Link>
</div>
Expand All @@ -41,7 +41,7 @@ export default function MobileNav() {

<button
onClick={handleSignOut}
className="text-gray-500 hover:text-gray-700 px-3 py-2 rounded-md text-sm font-medium"
className="text-gray-700 hover:text-gray-900 bg-gray-100 px-3 py-2 rounded-md text-sm font-medium"
>
Sign Out
</button>
Expand Down
133 changes: 133 additions & 0 deletions app/archive/page.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
'use client'

import { useEffect, useState } from 'react'
import Cookies from 'js-cookie'
import { MdDelete } from 'react-icons/md'
import TimeAgo from '../timeAgo'

function Archive() {
const [archiveURLs, setArchiveURLs] = useState([])
const [token, setToken] = useState(Cookies.get('jwt'))
const webURL = process.env.NEXT_PUBLIC_WEB_URL

useEffect(() => {
fetchArchiveURLs()
}, [])

const fetchArchiveURLs = async () => {
try {
const response = await fetch(webURL + 'shortener/archived', {
method: 'GET',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${token}`,
},
})

const archiveUrls = await response.json()
setArchiveURLs(archiveUrls)
} catch (error) {
console.error('Error fetching Archive URLs:', error)
}
}

const handleDeleteUrl = async (id) => {
try {
await fetch(webURL + `shortener/${id}`, {
method: 'DELETE',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${token}`,
},
})

const updatedArchiveUrl = archiveURLs.filter((url) => url.id !== id)
setArchiveURLs(updatedArchiveUrl)
} catch (error) {
console.error('Error Deleting Archive URL:', error)
}
}

return (
<section className="flex flex-col items-center min-h-screen bg-[#f4f4f5]">
{archiveURLs.length > 0 ? (
<div className="my-10 mx-2 w-full max-w-4xl border-2 rounded-3xl bg-white overflow-x-auto">
<div className="h-20 flex items-center mx-4">
<h2 className="font-bold">Archive History</h2>
</div>
<table className="table-auto w-full border-collapse border-none">
<thead>
<tr className="bg-gray-200">
<th className="px-4 py-2">Original URL</th>
<th className="px-4 py-2">Shortened URL</th>
<th className="px-4 py-2">Clicks</th>
<th className="px-4 py-2">Creation Date</th>
<th className="px-4 py-2">Last Updated</th>
<th className="px-4 py-2"></th>
</tr>
</thead>
<tbody>
{archiveURLs
.sort(
(a, b) =>
new Date(b.updatedAt).getTime() -
new Date(a.updatedAt).getTime()
)
.map(
({
id,
originalUrl,
shortUrl,
clicks,
archived,
createdAt,
updatedAt,
}) => (
<tr key={id} className="text-center">
<td className="px-4 py-2 break-all">
<a
href={originalUrl}
target="_blank"
rel="noopener noreferrer"
className="text-teal-500 hover:text-teal-700"
>
{originalUrl.substring(0, 10)}...
</a>
</td>
<td className="px-4 py-2">
<a
href={'https://gehe.fyi/' + shortUrl}
target="_blank"
rel="noopener noreferrer"
className="text-teal-500 hover:text-teal-700"
>
{shortUrl}
</a>
</td>
<td className="px-4 py-2">{clicks}</td>
<td className="px-4 py-2">
<TimeAgo date={createdAt} title={'Created at'} />
</td>
<td className="px-4 py-2">
<TimeAgo date={updatedAt} title={'Updated'} />
</td>
<td className="px-4 py-2">
<MdDelete
className="cursor-pointer hover:opacity-60"
onClick={() => handleDeleteUrl(id)}
/>
</td>
</tr>
)
)}
</tbody>
</table>
</div>
) : (
'fetching archive URLs...'
)}
</section>
)
}

export default Archive
2 changes: 1 addition & 1 deletion app/email-verification/page.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ export default function Verification() {
{/* OTP Verification */}
<div className="mb-4">
<label htmlFor="email" className="block text-gray-700 mb-2">
We've sent a code to
{`We've sent a code to`}
</label>
<input
type="text"
Expand Down
58 changes: 36 additions & 22 deletions app/navbar.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,21 @@
// components/Navbar.js
'use client'

import { useContext, useState } from 'react'
import { useContext, useEffect, useState } from 'react'
import Link from 'next/link'
import MobileNav from './MobileNav'
import { AuthContext } from './AuthContext'
import { useRouter } from 'next/navigation'
import { usePathname } from 'next/navigation'

export default function Navbar() {
const [isOpen, setIsOpen] = useState(false)
const [isAuthenticated, setIsAuthenticated] = useState(false)
const { token, logout } = useContext(AuthContext)
const router = useRouter()

const pathname = usePathname()

const bgColor = pathname === '/' ? 'bg-[#27272a]' : 'bg-[#f4f4f5]'
const color = pathname === '/' ? 'text-white' : 'text-black'

async function handleSignOut() {
try {
Expand All @@ -22,48 +26,58 @@ export default function Navbar() {
}
}
return (
<nav className="bg-white shadow-md">
<nav className={`${bgColor} shadow-md`}>
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div className="flex justify-between h-16">
{/* Logo or App Name */}
<div className="flex-shrink-0 flex items-center">
<Link href="/">
<span className="text-xl font-bold text-teal-600 cursor-pointer">
Shortify
<span className="text-xl md:text-2xl font-bold text-teal-600 cursor-pointer">
Gehe.fyi
</span>
</Link>
</div>

{/* Desktop Navigation Links and Buttons */}
<div className="hidden sm:ml-6 sm:flex sm:items-center">
<div className="flex space-x-4">

{token && (
<div className="hidden sm:ml-6 sm:flex sm:items-center">
<Link href="/">
<span className="text-gray-500 hover:text-gray-700 px-3 py-2 rounded-md text-sm font-medium cursor-pointer">
<span
className={`${color} hover:opacity-80 px-4 py-2 rounded-md text-base font-medium cursor-pointer`}
>
Home
</span>
</Link>
<Link href="/about">
<span className="text-gray-500 hover:text-gray-700 px-3 py-2 rounded-md text-sm font-medium cursor-pointer">
About
<Link href="/archive">
<span
className={`${color} hover:opacity-80 px-4 py-2 rounded-md text-base font-medium cursor-pointer`}
>
Archive
</span>
</Link>
<Link href="/contact">
<span className="text-gray-500 hover:text-gray-700 px-3 py-2 rounded-md text-sm font-medium cursor-pointer">
Contact
<Link href="/profile">
<span
className={`${color} hover:opacity-80 px-4 py-2 rounded-md text-base font-medium cursor-pointer`}
>
Profile
</span>
</Link>
</div>
)}

<div className="hidden sm:ml-6 sm:flex sm:items-center">
{token ? (
<>
{/* Sign Out Button */}

<button
onClick={handleSignOut}
className="text-gray-500 hover:text-gray-700 px-3 py-2 rounded-md text-sm font-medium"
>
Sign Out
</button>
<div className="flex space-x-4 items-center">
<button
onClick={handleSignOut}
className="w-full text-gray-700 hover:text-gray-900 bg-gray-100 hover:bg-gray-200 px-3 py-2 rounded-md text-base font-medium"
>
Sign Out
</button>
</div>
</>
) : (
<>
Expand Down
Loading

0 comments on commit 2be4dd7

Please sign in to comment.