From 3cb2dc97b215b188b3c0a7ac9eb6238a54757dca Mon Sep 17 00:00:00 2001 From: Aakash Singh Date: Sun, 15 Sep 2024 00:49:12 +0530 Subject: [PATCH 1/5] gmaps-dropdown --- .env.example | 7 +++++ package.json | 1 + prisma/schema.prisma | 15 ++-------- prisma/seed.ts | 15 ++-------- src/actions/job.action.ts | 28 +++++++++++++++---- src/app/[...404]/page.tsx | 4 +-- src/components/all-jobs.tsx | 2 +- src/components/gmaps-autosuggest.tsx | 42 ++++++++++++++++++++++++++++ src/components/job-form.tsx | 21 +++----------- src/layouts/footer.tsx | 12 ++++---- src/layouts/job-filters.tsx | 30 ++++++++++++++------ src/lib/validators/jobs.validator.ts | 9 +++--- src/services/jobs.services.ts | 4 +-- src/types/jobs.types.ts | 3 +- 14 files changed, 119 insertions(+), 74 deletions(-) create mode 100644 src/components/gmaps-autosuggest.tsx diff --git a/.env.example b/.env.example index 7f6a89f5..4782d417 100644 --- a/.env.example +++ b/.env.example @@ -15,3 +15,10 @@ NEXTAUTH_URL="http://localhost:3000" CDN_SZ_NAME= CDN_BASE_PATH= CDN_API_KEY= + +AWS_S3_REGION= +AWS_S3_ACCESS_KEY_ID= +AWS_S3_SECRET_ACCESS_KEY= +AWS_S3_BUCKET_NAME= + +NEXT_PUBLIC_GOOGLE_MAPS_API_KEY= diff --git a/package.json b/package.json index 18bbe24a..b81b6c17 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,7 @@ "dependencies": { "@aws-sdk/client-s3": "^3.645.0", "@aws-sdk/s3-request-presigner": "^3.645.0", + "@faker-js/faker": "^9.0.0", "@hookform/resolvers": "^3.9.0", "@prisma/client": "5.18.0", "@radix-ui/react-accordion": "^1.2.0", diff --git a/prisma/schema.prisma b/prisma/schema.prisma index baec4f15..e3eba55e 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -30,7 +30,8 @@ model Job { type String workMode WorkMode @map("work_mode") currency Currency @default(INR) - location JobLocations + city String + address String application String companyLogo String hasSalaryRange Boolean @default(false) @map("has_salary_range") @@ -58,15 +59,3 @@ enum Role { ADMIN } -enum JobLocations { - BANGLORE - DELHI - MUMBAI - CHENNAI - PUNE - HYDERABAD - KOLKATA - AHMEDABAD - JAIPUR - SURAT -} diff --git a/prisma/seed.ts b/prisma/seed.ts index 347cfcfc..3f01a17b 100644 --- a/prisma/seed.ts +++ b/prisma/seed.ts @@ -1,16 +1,14 @@ /* eslint-disable no-console */ import { Currency, Role, WorkMode } from '@prisma/client'; +import { faker } from '@faker-js/faker'; import bcrypt from 'bcryptjs'; import prisma from '../src/config/prisma.config'; -import { JobLocations } from '@prisma/client'; const users = [ { id: '1', name: 'Jack', email: 'user@gmail.com' }, { id: '2', name: 'Admin', email: 'admin@gmail.com', role: Role.ADMIN }, ]; -const locationArr = Object.keys(JobLocations); - let jobs = [ { id: '1', @@ -286,13 +284,6 @@ async function seedUsers() { } async function seedJobs() { - jobs = jobs.map((j, index) => { - return { - ...j, - location: - locationArr[index] !== undefined ? locationArr[index] : locationArr[3], - }; - }); try { await Promise.all( jobs.map(async (j) => @@ -311,8 +302,8 @@ async function seedJobs() { workMode: j.workMode, currency: j.currency, application: j.application, - //@ts-ignore - location: j.location, + city: faker.location.city(), + address: faker.location.streetAddress(), companyLogo: j.companyLogo, hasSalaryRange: j.hasSalaryRange, minSalary: j.minSalary, diff --git a/src/actions/job.action.ts b/src/actions/job.action.ts index 693740fb..3b752977 100644 --- a/src/actions/job.action.ts +++ b/src/actions/job.action.ts @@ -29,7 +29,8 @@ export const createJob = withServerActionAsyncCatcher< type, category, application, - location, + city, + address, companyLogo, title, workMode, @@ -52,7 +53,8 @@ export const createJob = withServerActionAsyncCatcher< hasSalaryRange, minSalary, maxSalary, - location, + city, + address, companyLogo, workMode, isVerifiedJob: false, // Default to false since there's no session to check for admin role @@ -73,8 +75,8 @@ export const getAllJobs = withServerActionAsyncCatcher< if (data?.salaryrange && !Array.isArray(data?.salaryrange)) { data.salaryrange = Array.of(data?.salaryrange); } - if (data?.location && !Array.isArray(data?.location)) { - data.location = Array.of(data?.location); + if (data?.city && !Array.isArray(data?.city)) { + data.city = Array.of(data?.city); } const result = JobQuerySchema.parse(data); const { filterQueries, orderBy, pagination } = getJobFilters(result); @@ -90,7 +92,8 @@ export const getAllJobs = withServerActionAsyncCatcher< title: true, description: true, companyName: true, - location: true, + city: true, + address: true, workMode: true, minSalary: true, maxSalary: true, @@ -131,7 +134,8 @@ export const getJobById = withServerActionAsyncCatcher< companyBio: true, companyEmail: true, companyLogo: true, - location: true, + city: true, + address: true, workMode: true, minSalary: true, maxSalary: true, @@ -142,3 +146,15 @@ export const getJobById = withServerActionAsyncCatcher< job, }).serialize(); }); + +export const getCityFilters = async () => { + const response = await prisma.job.findMany({ + select: { + city: true, + }, + }); + const cities = Array.from(new Set(response.map((res) => res.city))); + return new SuccessResponse(`Cities fetched successfully`, 200, { + cities, + }).serialize(); +}; diff --git a/src/app/[...404]/page.tsx b/src/app/[...404]/page.tsx index 42f7b062..5f8cb4d8 100644 --- a/src/app/[...404]/page.tsx +++ b/src/app/[...404]/page.tsx @@ -45,10 +45,10 @@ const Custom404Page = () => { className="bg-blue-600 hover:bg-blue-700 text-white font-semibold py-2 px-6 rounded-full transition-colors duration-300" > - +
Return to Homepage - +
diff --git a/src/components/all-jobs.tsx b/src/components/all-jobs.tsx index ce519806..67123e2c 100644 --- a/src/components/all-jobs.tsx +++ b/src/components/all-jobs.tsx @@ -40,7 +40,7 @@ const AllJobs = async ({ searchParams }: PaginatorProps) => {
- {job.location}{' '} + {job.address}{' '} ({job.workMode}) diff --git a/src/components/gmaps-autosuggest.tsx b/src/components/gmaps-autosuggest.tsx new file mode 100644 index 00000000..a13f04ee --- /dev/null +++ b/src/components/gmaps-autosuggest.tsx @@ -0,0 +1,42 @@ +import Script from 'next/script'; +import { Input } from './ui/input'; + +export type TgmapsAddress = { city: string; fullAddress: string }; + +export function GmapsAutocompleteAddress({ form }: { form: any }) { + let autocomplete: any = null; + + function onPlaceChanged() { + const { name, formatted_address } = autocomplete.getPlace(); + form.setValue('city', name); + form.setValue('address', formatted_address); + } + + function initializeGmaps() { + if ((window as any).google) { + autocomplete = new (window as any).google.maps.places.Autocomplete( + document.getElementById('autocomplete'), + { + types: ['(cities)'], + } + ); + autocomplete.addListener('place_changed', onPlaceChanged); + } + } + return ( + <> +