From f6424252e9389b604c99d144b44f716a2dc92f5b Mon Sep 17 00:00:00 2001 From: Paribesh Nepal <100255987+Paribesh01@users.noreply.github.com> Date: Thu, 12 Sep 2024 14:00:20 -0400 Subject: [PATCH 01/21] fix:fixed filter (#326) --- src/components/ui/paginator.tsx | 5 +++++ src/layouts/job-filters.tsx | 2 ++ 2 files changed, 7 insertions(+) diff --git a/src/components/ui/paginator.tsx b/src/components/ui/paginator.tsx index 604a6414..f780318e 100644 --- a/src/components/ui/paginator.tsx +++ b/src/components/ui/paginator.tsx @@ -18,6 +18,11 @@ export const PaginationPages = ({ baseUrl: string; }) => { const setQueryParams = useSetQueryParams(); + + if (currentPage > totalPages) { + setQueryParams({ page: '1' }); + } + function paginationHandler(page: number) { setQueryParams({ page: page.toString() }); } diff --git a/src/layouts/job-filters.tsx b/src/layouts/job-filters.tsx index bce63fa1..4c1f3113 100644 --- a/src/layouts/job-filters.tsx +++ b/src/layouts/job-filters.tsx @@ -29,12 +29,14 @@ import useSetQueryParams from '@/hooks/useSetQueryParams'; import { useEffect } from 'react'; import { WorkMode } from '@prisma/client'; import _ from 'lodash'; +import { DEFAULT_PAGE } from '@/config/app.config'; const JobFilters = ({ searchParams }: { searchParams: JobQuerySchemaType }) => { const setQueryParams = useSetQueryParams(); const form = useForm({ resolver: zodResolver(JobQuerySchema), defaultValues: { + page: DEFAULT_PAGE, workmode: searchParams.workmode, salaryrange: searchParams.salaryrange, location: searchParams.location, From 31320b2d9c0aa529491e5cc4d719725c339c834e Mon Sep 17 00:00:00 2001 From: Vineet Agarwal <91052168+VineeTagarwaL-code@users.noreply.github.com> Date: Sun, 15 Sep 2024 00:03:59 +0530 Subject: [PATCH 02/21] Update README.md --- README.md | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index f333fa5f..9f21185e 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # Project Name: Job Board - +[All about job board](https://marmalade-height-05f.notion.site/100xDevs-Job-board-ab8ca399180d49e4bc0c2ff5c81dfb08?pvs=25) ## Table of Contents - [Description](#description) @@ -11,14 +11,6 @@ Job Board is a platform designed to connect employers with potential employees. Employers can post job listings, and job seekers can apply for these positions. The application ensures a seamless and efficient job search and hiring process. -## Features - -- **User Registration and Authentication**: Secure and easy registration and login for both employers and job seekers. -- **Job Listings Management**: Employers can create, update, and manage job listings. -- **Job Applications**: Job seekers can browse listings and apply directly through the platform. -- **Profile Management**: Users can create and update their profiles with relevant information. -- **Search and Filter**: Advanced search and filtering options to find the perfect job or candidate. - ## Technologies - **Web-app**: Next.Js, TypeScript @@ -44,9 +36,23 @@ Follow these steps to set up the repository locally and run it. 1. Create a `.env` file in the root folder of your project. Update it following the convention of the `.env.example` file. Here's an example: ```bash + # + # Database + # DATABASE_URL="postgres://postgres:password@localhost:5432/postgres" + + # + # AUTH + # NEXTAUTH_SECRET="koXrQGB5TFD4KALDX4kAvnQ5RHHvAOIzB" NEXTAUTH_URL="http://localhost:3000" + + # + # Bunny CDN + # + CDN_SZ_NAME= + CDN_BASE_PATH= + CDN_API_KEY= ``` 2. To generate AUTH_SECRET, @@ -61,6 +67,7 @@ Follow these steps to set up the repository locally and run it. [Run in browser](https://www.cryptool.org/en/cto/openssl/) + ### Running the Project with Docker ```bash From 29822c1c97fc0e0b71029b07f148133cf759ca8c Mon Sep 17 00:00:00 2001 From: Vineet Agarwal <91052168+VineeTagarwaL-code@users.noreply.github.com> Date: Sun, 15 Sep 2024 00:04:31 +0530 Subject: [PATCH 03/21] Update .env.example --- .env.example | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/.env.example b/.env.example index 44f1a2c7..7f6a89f5 100644 --- a/.env.example +++ b/.env.example @@ -1,7 +1,17 @@ -DATABASE_URL="postgres://postgres:postgres@db:5432/job-board-db" -NEXTAUTH_SECRET="koXrQGB5TFDhiX47swxHW+4KALDX4kAvnQ5RHHvAOIzB" +# +# Database +# +DATABASE_URL="postgres://postgres:password@localhost:5432/postgres" + +# +# AUTH +# +NEXTAUTH_SECRET="koXrQGB5TFD4KALDX4kAvnQ5RHHvAOIzB" NEXTAUTH_URL="http://localhost:3000" -AWS_S3_REGION=your-aws-region -AWS_S3_ACCESS_KEY_ID=your-access-ID -AWS_S3_SECRET_ACCESS_KEY=your-access-key -AWS_S3_BUCKET_NAME=your-bucket \ No newline at end of file + +# +# Bunny CDN +# +CDN_SZ_NAME= +CDN_BASE_PATH= +CDN_API_KEY= From 90e9ee41d37cd63361ad4fdff1efe9ee7a437212 Mon Sep 17 00:00:00 2001 From: Vineet Agarwal <91052168+VineeTagarwaL-code@users.noreply.github.com> Date: Sun, 15 Sep 2024 01:13:36 +0530 Subject: [PATCH 04/21] Update README.md --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 9f21185e..053cc421 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,6 @@ # Project Name: Job Board -[All about job board](https://marmalade-height-05f.notion.site/100xDevs-Job-board-ab8ca399180d49e4bc0c2ff5c81dfb08?pvs=25) +[All about job board](https://marmalade-height-05f.notion.site/100xDevs-Job-board-ab8ca399180d49e4bc0c2ff5c81dfb08?pvs=25)
+[Job board bugs](https://marmalade-height-05f.notion.site/100xDevs-JOB-BOARD-Bugs-10115651c69c80478fc8f673a139bc60) ## Table of Contents - [Description](#description) From 167def8f1c928197795187b2af1a5db5a93287d7 Mon Sep 17 00:00:00 2001 From: Sujith Thirumalaisamy <108384868+SujithThirumalaisamy@users.noreply.github.com> Date: Sun, 15 Sep 2024 18:16:39 +0530 Subject: [PATCH 05/21] Migrated to BunnyCDN for image upload (#337) * Migrated to BunnyCDN for image upload * Reverted package.json * Refactored env for CDN * Added docs for image cdn domain config * Fixed lint --- .env.example | 6 ++-- README.md | 17 ++++++----- next.config.js | 4 +-- package.json | 2 ++ src/app/[...404]/page.tsx | 4 +-- src/app/api/s3-upload/route.ts | 43 -------------------------- src/app/api/upload-to-cdn/route.ts | 49 ++++++++++++++++++++++++++++++ src/components/job-form.tsx | 27 ++++++---------- 8 files changed, 77 insertions(+), 75 deletions(-) delete mode 100644 src/app/api/s3-upload/route.ts create mode 100644 src/app/api/upload-to-cdn/route.ts diff --git a/.env.example b/.env.example index 7f6a89f5..c9deb5b8 100644 --- a/.env.example +++ b/.env.example @@ -12,6 +12,6 @@ NEXTAUTH_URL="http://localhost:3000" # # Bunny CDN # -CDN_SZ_NAME= -CDN_BASE_PATH= -CDN_API_KEY= +CDN_API_KEY=api-key +CDN_BASE_UPLOAD_URL=https://sg.storage.bunnycdn.com/job-board/assets +CDN_BASE_ACCESS_URL=https://job-board.b-cdn.net/assets diff --git a/README.md b/README.md index 053cc421..fad88e89 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,8 @@ # Project Name: Job Board + [All about job board](https://marmalade-height-05f.notion.site/100xDevs-Job-board-ab8ca399180d49e4bc0c2ff5c81dfb08?pvs=25)
[Job board bugs](https://marmalade-height-05f.notion.site/100xDevs-JOB-BOARD-Bugs-10115651c69c80478fc8f673a139bc60) + ## Table of Contents - [Description](#description) @@ -38,12 +40,12 @@ Follow these steps to set up the repository locally and run it. ```bash # - # Database + # Database # DATABASE_URL="postgres://postgres:password@localhost:5432/postgres" # - # AUTH + # AUTH # NEXTAUTH_SECRET="koXrQGB5TFD4KALDX4kAvnQ5RHHvAOIzB" NEXTAUTH_URL="http://localhost:3000" @@ -51,12 +53,14 @@ Follow these steps to set up the repository locally and run it. # # Bunny CDN # - CDN_SZ_NAME= - CDN_BASE_PATH= - CDN_API_KEY= + CDN_API_KEY=api-key + CDN_BASE_UPLOAD_URL=https://sg.storage.bunnycdn.com/job-board/assets + CDN_BASE_ACCESS_URL=https://job-board.b-cdn.net/assets ``` -2. To generate AUTH_SECRET, +2. Change the hostname in `next.config.js` with your CDN access hostname by Ref of provided example. + +3. To generate AUTH_SECRET, Run this command in your terminal: @@ -68,7 +72,6 @@ Follow these steps to set up the repository locally and run it. [Run in browser](https://www.cryptool.org/en/cto/openssl/) - ### Running the Project with Docker ```bash diff --git a/next.config.js b/next.config.js index 8e2fe13f..ae3b9839 100644 --- a/next.config.js +++ b/next.config.js @@ -10,8 +10,8 @@ const nextConfig = { remotePatterns: [ { protocol: 'https', - //Add aws s3 bucket hostname - hostname: '', //example - youraws.s3.ap-south-2.amazonaws.com + //Change it with your cdn access domain here + hostname: 'job-board.b-cdn.net', }, ], }, diff --git a/package.json b/package.json index 18bbe24a..36636e1b 100644 --- a/package.json +++ b/package.json @@ -36,6 +36,7 @@ "@radix-ui/react-switch": "^1.1.0", "@radix-ui/react-toast": "^1.2.1", "@types/lodash": "^4.17.7", + "@types/uuid": "^10.0.0", "@uidotdev/usehooks": "^2.4.1", "bcryptjs": "^2.4.3", "class-variance-authority": "^0.7.0", @@ -55,6 +56,7 @@ "react-quill": "^2.0.0", "tailwind-merge": "^2.4.0", "tailwindcss-animate": "^1.0.7", + "uuid": "^10.0.0", "vaul": "^0.9.1", "zod": "^3.23.8", "zod-error": "^1.5.0" diff --git a/src/app/[...404]/page.tsx b/src/app/[...404]/page.tsx index 42f7b062..1fec2b23 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/app/api/s3-upload/route.ts b/src/app/api/s3-upload/route.ts deleted file mode 100644 index b3102bf3..00000000 --- a/src/app/api/s3-upload/route.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { NextResponse } from 'next/server'; -import { getSignedUrl } from '@aws-sdk/s3-request-presigner'; -import { S3Client, PutObjectCommand } from '@aws-sdk/client-s3'; - -const s3Client = new S3Client({ - region: process.env.AWS_S3_REGION!, - credentials: { - accessKeyId: process.env.AWS_S3_ACCESS_KEY_ID!, - secretAccessKey: process.env.AWS_S3_SECRET_ACCESS_KEY!, - }, -}); - -export async function GET(req: Request): Promise { - const url = new URL(req.url); - const file = url.searchParams.get('file'); - const fileType = url.searchParams.get('fileType'); - const uniqueKey = url.searchParams.get('uniqueKey'); - - if (!file || !fileType || !uniqueKey) { - return NextResponse.json( - { error: 'File name and file type are required' }, - { status: 400 } - ); - } - - try { - const command = new PutObjectCommand({ - Bucket: process.env.AWS_S3_BUCKET_NAME!, - Key: uniqueKey, - ContentType: fileType, - }); - - const signedUrl = await getSignedUrl(s3Client, command, { expiresIn: 60 }); - - return NextResponse.json({ url: signedUrl }); - } catch (error) { - console.error('Error generating presigned URL:', error); - return NextResponse.json( - { error: 'Internal server error' }, - { status: 500 } - ); - } -} diff --git a/src/app/api/upload-to-cdn/route.ts b/src/app/api/upload-to-cdn/route.ts new file mode 100644 index 00000000..35167c03 --- /dev/null +++ b/src/app/api/upload-to-cdn/route.ts @@ -0,0 +1,49 @@ +import { NextResponse } from 'next/server'; +import { v4 as uuidv4 } from 'uuid'; + +const CDN_BASE_UPLOAD_URL = process.env.CDN_BASE_UPLOAD_URL; +const CDN_BASE_ACCESS_URL = process.env.CDN_BASE_ACCESS_URL; +const CDN_API_KEY = process.env.CDN_API_KEY!; + +export async function POST(req: Request): Promise { + try { + const formData = await req.formData(); + const file = formData.get('file') as File; + const uniqueFileName = formData.get('uniqueFileName') || uuidv4(); // Generate unique key if not provided + + if (!file) { + return NextResponse.json({ error: 'File is required' }, { status: 400 }); + } + + const uploadUrl = `${CDN_BASE_UPLOAD_URL}/${uniqueFileName}`; + + const fileBuffer = Buffer.from(await file.arrayBuffer()); + + const response = await fetch(uploadUrl, { + method: 'PUT', + headers: { + AccessKey: CDN_API_KEY, + 'Content-Type': 'application/octet-stream', + }, + body: fileBuffer, + }); + + if (response.ok) { + return NextResponse.json({ + message: 'File uploaded successfully', + url: `${CDN_BASE_ACCESS_URL}/${uniqueFileName}`, + }); + } else { + return NextResponse.json( + { error: 'Failed to upload file' }, + { status: response.status } + ); + } + } catch (error) { + console.error('Error uploading file to BunnyCDN:', error); + return NextResponse.json( + { error: 'Internal server error' }, + { status: 500 } + ); + } +} diff --git a/src/components/job-form.tsx b/src/components/job-form.tsx index 3afb1c5c..8bcd03a7 100644 --- a/src/components/job-form.tsx +++ b/src/components/job-form.tsx @@ -74,29 +74,20 @@ const PostJobForm = () => { formData.append('file', file); try { - const uniqueFileName = `${file.name}-${Date.now()}`; - const fileType = file.type; + const uniqueFileName = `${Date.now()}-${file.name}`; + formData.append('uniqueFileName', uniqueFileName); - const res = await fetch( - `/api/s3-upload?file=${encodeURIComponent(file.name)}&fileType=${encodeURIComponent(fileType)}&uniqueKey=${encodeURIComponent(uniqueFileName)}` - ); - if (!res.ok) { - throw new Error('Failed to fetch presigned URL'); - } - - const { url: presignedUrl } = await res.json(); - const upload = await fetch(presignedUrl, { - method: 'PUT', - body: file, - headers: { 'Content-Type': fileType }, + const res = await fetch(`/api/upload-to-cdn`, { + method: 'POST', + body: formData, }); - if (!upload.ok) { - throw new Error('Upload failed'); + if (!res.ok) { + throw new Error('Failed to upload image'); } - const pubUrl = presignedUrl.split('?')[0]; - return pubUrl; + const uploadRes = await res.json(); + return uploadRes.url; } catch (error) { console.error('Image upload failed:', error); } From 985b35c0c3aaf100561e57fd9948521cae4ddafc Mon Sep 17 00:00:00 2001 From: Aakash Singh <78924853+aakash2330@users.noreply.github.com> Date: Sun, 15 Sep 2024 18:21:54 +0530 Subject: [PATCH 06/21] [feature]: added google api for custom job location * gmaps-dropdown * company-logo-url-fix * workflow-pipeline-prettier-fix * prettier-fix * failure-syntax-fix * ui changes + husky pre-commit * prettier-fix --------- Co-authored-by: Aakash Singh Co-authored-by: Vineet Agarwal <91052168+VineeTagarwaL-code@users.noreply.github.com> --- .env.example | 4 +++ .github/workflows/ci.yaml | 6 +++- package.json | 13 ++++++++- prisma/schema.prisma | 15 ++-------- prisma/seed.ts | 15 ++-------- src/actions/job.action.ts | 28 +++++++++++++++---- src/app/globals.css | 27 ++++++++++++++++++ src/components/all-jobs.tsx | 2 +- src/components/gmaps-autosuggest.tsx | 42 ++++++++++++++++++++++++++++ src/components/job-form.tsx | 24 ++++------------ 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 +- 15 files changed, 159 insertions(+), 75 deletions(-) create mode 100644 src/components/gmaps-autosuggest.tsx diff --git a/.env.example b/.env.example index c9deb5b8..f8f03c54 100644 --- a/.env.example +++ b/.env.example @@ -15,3 +15,7 @@ NEXTAUTH_URL="http://localhost:3000" CDN_API_KEY=api-key CDN_BASE_UPLOAD_URL=https://sg.storage.bunnycdn.com/job-board/assets CDN_BASE_ACCESS_URL=https://job-board.b-cdn.net/assets + + +NEXT_PUBLIC_GOOGLE_MAPS_API_KEY= + diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 424c68cc..d189e867 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -27,6 +27,10 @@ jobs: - name: Run format check run: npm run check + + - name: Run format fix if check fails + if: ${{ failure() }} + run: npm run format - name: Run build - run: npm run build \ No newline at end of file + run: npm run build diff --git a/package.json b/package.json index 36636e1b..9ccd4412 100644 --- a/package.json +++ b/package.json @@ -9,16 +9,27 @@ "lint": "next lint", "dev:docker": "npm run db:seed & next dev", "db:seed": "npx prisma db push & npx prisma db seed", - "format": "prettier --write \"**/*.{ts,tsx,js,jsx,md,mdx,css}\"", "check": "prettier --check \"**/*.{ts,tsx,js,jsx,md,mdx,css}\"", + "format": "prettier --write \"**/*.{ts,tsx,js,jsx,md,mdx,css}\"", "prepare": "husky" }, + "husky": { + "hooks": { + "pre-commit": "lint-staged" + } + }, + "lint-staged": { + "**/*.{ts,tsx,js,jsx,md,mdx,css}": [ + "prettier --write" + ] + }, "prisma": { "seed": "ts-node --compiler-options {\"module\":\"CommonJS\"} prisma/seed.ts" }, "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/globals.css b/src/app/globals.css index b3c421ed..301c0d12 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -345,3 +345,30 @@ overflow-x: hidden !important; /* Allow horizontal scrolling */ overflow-y: hidden !important; /* Hide vertical overflow */ } + +.pac-container { + background-color: black !important; + color: #fff; + border-radius: 8px; + padding-top: 5px; + padding-bottom: 5px; + font-family: '__Inter_36bd41', '__Inter_Fallback', sans-serif !important; + font-size: 14px !important; +} +.pac-item { + color: #fff !important; + border: none; + font-size: 14px; +} +.pac-item:hover { + background-color: hsl(0, 0%, 14.9%) !important; + cursor: pointer; +} +.pac-item-query { + color: white; + font-weight: bold; +} + +.pac-logo.hdpi::after { + content: none; +} 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 ( + <> +