Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 54 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 7 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,21 @@
"lint": "eslint"
},
"dependencies": {
"framer-motion": "^12.23.21",
"next": "15.5.4",
"react": "19.1.0",
"react-dom": "19.1.0",
"next": "15.5.4"
"react-icons": "^5.5.0"
},
"devDependencies": {
"typescript": "^5",
"@eslint/eslintrc": "^3",
"@tailwindcss/postcss": "^4",
"@types/node": "^20",
"@types/react": "^19",
"@types/react-dom": "^19",
"@tailwindcss/postcss": "^4",
"tailwindcss": "^4",
"eslint": "^9",
"eslint-config-next": "15.5.4",
"@eslint/eslintrc": "^3"
"tailwindcss": "^4",
"typescript": "^5"
}
}
File renamed without changes.
2 changes: 1 addition & 1 deletion src/app/api/services/route.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { NextRequest, NextResponse } from 'next/server'
import workersData from '../../../../workers.json'
import workersData from "../../../../public/workers.json"

// GET /api/services
export async function GET(request: NextRequest) {
Expand Down
2 changes: 1 addition & 1 deletion src/app/api/workers/route.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { NextResponse } from 'next/server'
import workersData from '../../../../workers.json'
import workersData from '../../../../public/workers.json'

export async function GET() {
try {
Expand Down
14 changes: 8 additions & 6 deletions src/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
import type { Metadata } from "next";
import { Geist, Geist_Mono } from "next/font/google";
import "./globals.css";
import Navbar from "@/component/Navbar";

export const metadata: Metadata = {
title: "SolveEase",
description: "Hire skilled workers and manage services efficiently.",
};

const geistSans = Geist({
variable: "--font-geist-sans",
Expand All @@ -12,11 +18,6 @@ const geistMono = Geist_Mono({
subsets: ["latin"],
});

export const metadata: Metadata = {
title: "Create Next App",
description: "Generated by create next app",
};

export default function RootLayout({
children,
}: Readonly<{
Expand All @@ -27,7 +28,8 @@ export default function RootLayout({
<body
className={`${geistSans.variable} ${geistMono.variable} antialiased`}
>
{children}
<Navbar />
<main>{children}</main>
</body>
</html>
);
Expand Down
63 changes: 9 additions & 54 deletions src/app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,57 +1,12 @@
'use client'
import { WorkerType } from '@/types/workers'
import Image from 'next/image'
import { useState, useEffect } from 'react'
// src/app/workers/page.tsx
import WorkersPageClient from "@/component/WorkerPageClient";

export default function WorkersPage() {
const [workersData, setWorkersData] = useState<WorkerType[]>([])

useEffect(() => {
const loadData = async () => {
try {
const response = await import('../../workers.json')
setWorkersData(response.default)
} catch (error) {
console.error('Failed to load workers:', error)
}
}
loadData()
loadData()
}, [])
export const metadata = {
title: "Workers | SolveEase",
description:
"Hire skilled workers for various services. Browse workers by service type and price.",
};

return (
<main className='container mx-auto px-4 py-8 bg-[#000000]'>
<h1 className='text-3xl font-bold mb-8 text-center'>Our Workers</h1>

<div className='grid grid-cols-1 sm:grid-cols-2 md:grid-cols-1 gap-6'>
{workersData
.filter((worker) => worker.pricePerDay > 0)
.filter((worker) => worker.id !== null)
.sort((a, b) => a.name.localeCompare(b.name))
.map((worker: WorkerType) => (
<div
key={worker.id}
className='border rounded-lg overflow-hidden shadow hover:shadow-lg transition-shadow duration-300'
>
<div className='w-full h-48 relative'>
<Image
src={worker.image}
alt={worker.name}
fill
className='object-cover'
priority={worker.id <= 10}
/>
</div>
<div className='p-4'>
<h2 className='text-xl font-semibold'>{worker.name}</h2>
<p className='text-gray-600'>{worker.service}</p>
<p className='mt-2 font-medium'>
₹{Math.round(worker.pricePerDay * 1.18)} / day
</p>
</div>
</div>
))}
</div>
</main>
)
export default function WorkersPage() {
return <WorkersPageClient />;
}
72 changes: 72 additions & 0 deletions src/component/Navbar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
"use client";
import { useState } from "react";
import Link from "next/link";
import { HiMenu, HiX } from "react-icons/hi";



export default function Navbar() {
const [isOpen, setIsOpen] = useState(false);

const toggleMenu = () => setIsOpen(!isOpen);

const navLinks = [
{ name: "Home", href: "/" },
{ name: "Workers", href: "/workers" },
{ name: "Contact", href: "/contact" },
];

return (
<nav className="sticky top-0 z-50 bg-white shadow-md">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-2">
<div className="flex justify-between h-16 items-center">
{/* Logo */}
<Link href="/" className="text-2xl font-bold text-indigo-600">
SolveEase
</Link>

{/* Desktop Links */}
<div className="hidden md:flex space-x-6">
{navLinks.map((link) => (
<Link
key={link.name}
href={link.href}
className="text-gray-700 hover:text-indigo-600 font-medium transition-colors duration-300"
>
{link.name}
</Link>
))}
</div>

{/* Mobile Hamburger */}
<div className="md:hidden">
<button
onClick={toggleMenu}
className="text-gray-700 hover:text-indigo-600 focus:outline-none"
>
{isOpen ? <HiX size={28} /> : <HiMenu size={28} />}
</button>
</div>
</div>
</div>

{/* Mobile Menu */}
{isOpen && (
<div className="md:hidden bg-white border-t border-gray-200">
<div className="px-2 pt-2 pb-4 space-y-1">
{navLinks.map((link) => (
<Link
key={link.name}
href={link.href}
className="block px-3 py-2 rounded-md text-base font-medium text-gray-700 hover:bg-indigo-50 hover:text-indigo-600 transition-colors duration-300"
onClick={() => setIsOpen(false)} // close menu on click
>
{link.name}
</Link>
))}
</div>
</div>
)}
</nav>
);
}
Loading