diff --git a/.eslintrc.json b/.eslintrc.json index 1fccac7..4da34a4 100755 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -98,7 +98,8 @@ "@typescript-eslint/explicit-module-boundary-types": "off", "@typescript-eslint/no-this-alias": "off", "@typescript-eslint/no-unnecessary-type-constraint": "off", - "@typescript-eslint/ban-types": "off" + "@typescript-eslint/ban-types": "off", + "no-console": "warn" }, "overrides": [ { diff --git a/.husky/pre-commit b/.husky/pre-commit index 7259a3d..20fe722 100755 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -1,4 +1,4 @@ -npm run format:check npm run format:fix +npm run format:check npm run lint git add . diff --git a/app/manifest.ts b/app/manifest.ts new file mode 100644 index 0000000..c61b356 --- /dev/null +++ b/app/manifest.ts @@ -0,0 +1,25 @@ +import type { MetadataRoute } from "next"; + +export default function manifest(): MetadataRoute.Manifest { + return { + name: "Job Junction", + short_name: "JJ", + description: "A Web App of job junction", + start_url: "/", + display: "standalone", + background_color: "#ffffff", + theme_color: "#000000", + icons: [ + { + src: "/favicon/web-app-manifest-192x192.png", + sizes: "192x192", + type: "image/png", + }, + { + src: "/favicon/web-app-manifest-512x512.png", + sizes: "512x512", + type: "image/png", + }, + ], + }; +} diff --git a/components/Navbar/Navbar.tsx b/components/Navbar/Navbar.tsx index 2dc490d..ac38fbc 100755 --- a/components/Navbar/Navbar.tsx +++ b/components/Navbar/Navbar.tsx @@ -15,6 +15,7 @@ import { SheetTrigger, } from "@/components/ui/sheet"; import GetNotification from "../GetNotification"; +import PWAInstallButton from "@/components/PwaInstallBtn"; export default function Navbar() { const session = useSession(); @@ -30,7 +31,7 @@ export default function Navbar() { src={"/Images/jj-logo.png"} width={500} height={500} - className="w-12 rounded-md" + className="hidden w-12 rounded-md sm:block" alt="JJ" /> @@ -40,7 +41,8 @@ export default function Navbar() { -
+
+ {session.status === "authenticated" ? ( <> diff --git a/components/PwaInstallBtn.tsx b/components/PwaInstallBtn.tsx index b2bffd2..fca5a96 100755 --- a/components/PwaInstallBtn.tsx +++ b/components/PwaInstallBtn.tsx @@ -1,30 +1,29 @@ "use client"; - import { BeforeInstallPromptEvent } from "@/types/types"; import React, { useEffect, useState } from "react"; -import { Download, Briefcase } from "lucide-react"; -import { motion } from "framer-motion"; -import { poppins } from "@/utils/fonts/font"; -import Link from "next/link"; +import { + Drawer, + DrawerContent, + DrawerDescription, + DrawerHeader, + DrawerTitle, + DrawerTrigger, +} from "@/components/ui/drawer"; +import { Button } from "@/components/ui/button"; +import { Download, Zap } from "lucide-react"; +import Image from "next/image"; +import { toast } from "sonner"; const PWAInstallButton = () => { const [deferredEvent, setDeferredEvent] = useState(null); - const [installable, setInstallable] = useState(false); useEffect(() => { const transferEvent = (e: BeforeInstallPromptEvent) => { e.preventDefault(); setDeferredEvent(e); - setInstallable(true); - localStorage.setItem("pwaInstallable", "true"); }; - const storedInstallable = localStorage.getItem("pwaInstallable"); - if (storedInstallable === "true") { - setInstallable(true); - } - window.addEventListener("beforeinstallprompt", transferEvent); return () => { @@ -36,49 +35,50 @@ const PWAInstallButton = () => { if (deferredEvent) { deferredEvent.prompt(); setDeferredEvent(null); - setInstallable(false); - localStorage.removeItem("pwaInstallable"); + } else { + toast.info("Install prompt is not available.", { + style: { + backgroundColor: "grey", + color: "white", + }, + }); } }; return ( - <> - {installable ? ( - -

Get App

- -
- ) : ( - - -

Post Job

- - - -
- )} - + + + + + + + +
+ jj-logo +

Job Junction

+
+ +
+ + Find your Next Opportunity With Job Junction + +
+
+
); }; diff --git a/components/ui/drawer.tsx b/components/ui/drawer.tsx new file mode 100644 index 0000000..350f8b6 --- /dev/null +++ b/components/ui/drawer.tsx @@ -0,0 +1,118 @@ +"use client"; + +import * as React from "react"; +import { Drawer as DrawerPrimitive } from "vaul"; + +import { cn } from "@/lib/utils"; + +const Drawer = ({ + shouldScaleBackground = true, + ...props +}: React.ComponentProps) => ( + +); +Drawer.displayName = "Drawer"; + +const DrawerTrigger = DrawerPrimitive.Trigger; + +const DrawerPortal = DrawerPrimitive.Portal; + +const DrawerClose = DrawerPrimitive.Close; + +const DrawerOverlay = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +DrawerOverlay.displayName = DrawerPrimitive.Overlay.displayName; + +const DrawerContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + + + +
+ {children} + + +)); +DrawerContent.displayName = "DrawerContent"; + +const DrawerHeader = ({ + className, + ...props +}: React.HTMLAttributes) => ( +
+); +DrawerHeader.displayName = "DrawerHeader"; + +const DrawerFooter = ({ + className, + ...props +}: React.HTMLAttributes) => ( +
+); +DrawerFooter.displayName = "DrawerFooter"; + +const DrawerTitle = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +DrawerTitle.displayName = DrawerPrimitive.Title.displayName; + +const DrawerDescription = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +DrawerDescription.displayName = DrawerPrimitive.Description.displayName; + +export { + Drawer, + DrawerPortal, + DrawerOverlay, + DrawerTrigger, + DrawerClose, + DrawerContent, + DrawerHeader, + DrawerFooter, + DrawerTitle, + DrawerDescription, +}; diff --git a/package-lock.json b/package-lock.json index d358ffc..e926b83 100755 --- a/package-lock.json +++ b/package-lock.json @@ -15,7 +15,7 @@ "@radix-ui/react-alert-dialog": "^1.1.1", "@radix-ui/react-avatar": "^1.1.0", "@radix-ui/react-checkbox": "^1.1.1", - "@radix-ui/react-dialog": "^1.1.1", + "@radix-ui/react-dialog": "^1.1.2", "@radix-ui/react-dropdown-menu": "^2.1.1", "@radix-ui/react-hover-card": "^1.1.1", "@radix-ui/react-popover": "^1.1.1", @@ -70,6 +70,7 @@ "streamifier": "^0.1.1", "tailwind-merge": "^2.4.0", "tailwindcss-animate": "^1.0.7", + "vaul": "^1.1.1", "web-push": "^3.6.7", "zod": "^3.23.8" }, @@ -88,7 +89,7 @@ "eslint-config-prettier": "^9.1.0", "eslint-plugin-prettier": "^5.2.1", "postcss": "^8", - "prettier": "^3.3.3", + "prettier": "^3.4.0", "prettier-plugin-tailwindcss": "^0.6.8", "prisma": "^5.18.0", "tailwindcss": "^3.4.4", @@ -2443,6 +2444,42 @@ } } }, + "node_modules/@radix-ui/react-alert-dialog/node_modules/@radix-ui/react-dialog": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.1.1.tgz", + "integrity": "sha512-zysS+iU4YP3STKNS6USvFVqI4qqx8EpiwmT5TuCApVEBca+eRCbONi4EgzfNSuVnOXvC5UPHHMjs8RXO6DH9Bg==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.0", + "@radix-ui/react-compose-refs": "1.1.0", + "@radix-ui/react-context": "1.1.0", + "@radix-ui/react-dismissable-layer": "1.1.0", + "@radix-ui/react-focus-guards": "1.1.0", + "@radix-ui/react-focus-scope": "1.1.0", + "@radix-ui/react-id": "1.1.0", + "@radix-ui/react-portal": "1.1.1", + "@radix-ui/react-presence": "1.1.0", + "@radix-ui/react-primitive": "2.0.0", + "@radix-ui/react-slot": "1.1.0", + "@radix-ui/react-use-controllable-state": "1.1.0", + "aria-hidden": "^1.1.1", + "react-remove-scroll": "2.5.7" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-arrow": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.0.tgz", @@ -2639,24 +2676,67 @@ } }, "node_modules/@radix-ui/react-dialog": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.1.1.tgz", - "integrity": "sha512-zysS+iU4YP3STKNS6USvFVqI4qqx8EpiwmT5TuCApVEBca+eRCbONi4EgzfNSuVnOXvC5UPHHMjs8RXO6DH9Bg==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.1.2.tgz", + "integrity": "sha512-Yj4dZtqa2o+kG61fzB0H2qUvmwBA2oyQroGLyNtBj1beo1khoQ3q1a2AO8rrQYjd8256CO9+N8L9tvsS+bnIyA==", + "license": "MIT", "dependencies": { "@radix-ui/primitive": "1.1.0", "@radix-ui/react-compose-refs": "1.1.0", - "@radix-ui/react-context": "1.1.0", - "@radix-ui/react-dismissable-layer": "1.1.0", - "@radix-ui/react-focus-guards": "1.1.0", + "@radix-ui/react-context": "1.1.1", + "@radix-ui/react-dismissable-layer": "1.1.1", + "@radix-ui/react-focus-guards": "1.1.1", "@radix-ui/react-focus-scope": "1.1.0", "@radix-ui/react-id": "1.1.0", - "@radix-ui/react-portal": "1.1.1", - "@radix-ui/react-presence": "1.1.0", + "@radix-ui/react-portal": "1.1.2", + "@radix-ui/react-presence": "1.1.1", "@radix-ui/react-primitive": "2.0.0", "@radix-ui/react-slot": "1.1.0", "@radix-ui/react-use-controllable-state": "1.1.0", "aria-hidden": "^1.1.1", - "react-remove-scroll": "2.5.7" + "react-remove-scroll": "2.6.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-context": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.1.tgz", + "integrity": "sha512-UASk9zi+crv9WteK/NU4PLvOoL3OuE6BWVKNF6hPRBtYBDXQ2u5iu3O59zUlJiTVvkyuycnqrztsHVJwcK9K+Q==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-dismissable-layer": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.1.tgz", + "integrity": "sha512-QSxg29lfr/xcev6kSz7MAlmDnzbP1eI/Dwn3Tp1ip0KT5CUELsxkekFEMVBEoykI3oV39hKT4TKZzBNMbcTZYQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.0", + "@radix-ui/react-compose-refs": "1.1.0", + "@radix-ui/react-primitive": "2.0.0", + "@radix-ui/react-use-callback-ref": "1.1.0", + "@radix-ui/react-use-escape-keydown": "1.1.0" }, "peerDependencies": { "@types/react": "*", @@ -2673,6 +2753,94 @@ } } }, + "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-focus-guards": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.1.tgz", + "integrity": "sha512-pSIwfrT1a6sIoDASCSpFwOasEwKTZWDw/iBdtnqKO7v6FeOzYJ7U53cPzYFVR3geGGXgVHaH+CdngrrAzqUGxg==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-portal": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.2.tgz", + "integrity": "sha512-WeDYLGPxJb/5EGBoedyJbT0MpoULmwnIPMJMSldkuiMsBAv7N1cRdsTWZWht9vpPOiN3qyiGAtbK2is47/uMFg==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-primitive": "2.0.0", + "@radix-ui/react-use-layout-effect": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-presence": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.1.tgz", + "integrity": "sha512-IeFXVi4YS1K0wVZzXNrbaaUvIJ3qdY+/Ih4eHFhWA9SwGR9UDX7Ck8abvL57C4cv3wwMvUE0OG69Qc3NCcTe/A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.0", + "@radix-ui/react-use-layout-effect": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-dialog/node_modules/react-remove-scroll": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.6.0.tgz", + "integrity": "sha512-I2U4JVEsQenxDAKaVa3VZ/JeJZe0/2DxPWL8Tj8yLKctQJQiZM52pn/GWFpSp8dftjM3pSAHVJZscAnC/y+ySQ==", + "license": "MIT", + "dependencies": { + "react-remove-scroll-bar": "^2.3.6", + "react-style-singleton": "^2.2.1", + "tslib": "^2.1.0", + "use-callback-ref": "^1.3.0", + "use-sidecar": "^1.1.2" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-direction": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.1.0.tgz", @@ -9031,10 +9199,11 @@ } }, "node_modules/prettier": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.3.tgz", - "integrity": "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==", + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.4.0.tgz", + "integrity": "sha512-/OXNZcLyWkfo13ofOW5M7SLh+k5pnIs07owXK2teFpnfaOEcycnSy7HQxldaVX1ZP/7Q8oO1eDuQJNwbomQq5Q==", "dev": true, + "license": "MIT", "bin": { "prettier": "bin/prettier.cjs" }, @@ -11071,6 +11240,19 @@ "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", "devOptional": true }, + "node_modules/vaul": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/vaul/-/vaul-1.1.1.tgz", + "integrity": "sha512-+ejzF6ffQKPcfgS7uOrGn017g39F8SO4yLPXbBhpC7a0H+oPqPna8f1BUfXaz8eU4+pxbQcmjxW+jWBSbxjaFg==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-dialog": "^1.1.1" + }, + "peerDependencies": { + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0" + } + }, "node_modules/w3c-keyname": { "version": "2.2.8", "resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.8.tgz", diff --git a/package.json b/package.json index 8794bdf..0589cd5 100755 --- a/package.json +++ b/package.json @@ -25,7 +25,7 @@ "@radix-ui/react-alert-dialog": "^1.1.1", "@radix-ui/react-avatar": "^1.1.0", "@radix-ui/react-checkbox": "^1.1.1", - "@radix-ui/react-dialog": "^1.1.1", + "@radix-ui/react-dialog": "^1.1.2", "@radix-ui/react-dropdown-menu": "^2.1.1", "@radix-ui/react-hover-card": "^1.1.1", "@radix-ui/react-popover": "^1.1.1", @@ -80,6 +80,7 @@ "streamifier": "^0.1.1", "tailwind-merge": "^2.4.0", "tailwindcss-animate": "^1.0.7", + "vaul": "^1.1.1", "web-push": "^3.6.7", "zod": "^3.23.8" }, @@ -98,7 +99,7 @@ "eslint-config-prettier": "^9.1.0", "eslint-plugin-prettier": "^5.2.1", "postcss": "^8", - "prettier": "^3.3.3", + "prettier": "^3.4.0", "prettier-plugin-tailwindcss": "^0.6.8", "prisma": "^5.18.0", "tailwindcss": "^3.4.4", diff --git a/public/favicon/apple-touch-icon.png b/public/favicon/apple-touch-icon.png new file mode 100644 index 0000000..5850253 Binary files /dev/null and b/public/favicon/apple-touch-icon.png differ diff --git a/public/favicon/favicon-96x96.png b/public/favicon/favicon-96x96.png new file mode 100644 index 0000000..0d7c149 Binary files /dev/null and b/public/favicon/favicon-96x96.png differ diff --git a/public/favicon/favicon.ico b/public/favicon/favicon.ico new file mode 100644 index 0000000..08098b8 Binary files /dev/null and b/public/favicon/favicon.ico differ diff --git a/public/favicon/favicon.svg b/public/favicon/favicon.svg new file mode 100644 index 0000000..4a5a63c --- /dev/null +++ b/public/favicon/favicon.svg @@ -0,0 +1,3 @@ + \ No newline at end of file diff --git a/public/favicon/site.webmanifest b/public/favicon/site.webmanifest new file mode 100644 index 0000000..649d506 --- /dev/null +++ b/public/favicon/site.webmanifest @@ -0,0 +1,21 @@ +{ + "name": "MyWebSite", + "short_name": "MySite", + "icons": [ + { + "src": "/web-app-manifest-192x192.png", + "sizes": "192x192", + "type": "image/png", + "purpose": "maskable" + }, + { + "src": "/web-app-manifest-512x512.png", + "sizes": "512x512", + "type": "image/png", + "purpose": "maskable" + } + ], + "theme_color": "#ffffff", + "background_color": "#8a8a8a", + "display": "standalone" +} diff --git a/public/favicon/web-app-manifest-192x192.png b/public/favicon/web-app-manifest-192x192.png new file mode 100644 index 0000000..71457ae Binary files /dev/null and b/public/favicon/web-app-manifest-192x192.png differ diff --git a/public/favicon/web-app-manifest-512x512.png b/public/favicon/web-app-manifest-512x512.png new file mode 100644 index 0000000..673533e Binary files /dev/null and b/public/favicon/web-app-manifest-512x512.png differ diff --git a/tailwind.config.ts b/tailwind.config.ts index 17e73a2..46fc8b0 100755 --- a/tailwind.config.ts +++ b/tailwind.config.ts @@ -1,10 +1,11 @@ import type { Config } from "tailwindcss"; +//eslint-disable-next-line const defaultTheme = require("tailwindcss/defaultTheme"); - +//eslint-disable-next-line const colors = require("tailwindcss/colors"); const { default: flattenColorPalette, -} = require("tailwindcss/lib/util/flattenColorPalette"); +} = require("tailwindcss/lib/util/flattenColorPalette"); //eslint-disable-line const config = { darkMode: ["class"], @@ -43,7 +44,6 @@ const config = { hoverBorder: "#1f2636", primaryTestimonalBg: "#020817", secondaryTestimoanlBg: "#101b3d", - primaryViolet: "#2b2638", inputBg: "#262a34", border: "hsl(var(--border))", @@ -134,12 +134,12 @@ const config = { }, }, }, - plugins: [require("tailwindcss-animate"), addVariablesForColors], + plugins: [require("tailwindcss-animate"), addVariablesForColors], //eslint-disable-line } satisfies Config; function addVariablesForColors({ addBase, theme }: any) { - let allColors = flattenColorPalette(theme("colors")); - let newVars = Object.fromEntries( + const allColors = flattenColorPalette(theme("colors")); + const newVars = Object.fromEntries( Object.entries(allColors).map(([key, val]) => [`--${key}`, val]), );