├── public ├── favicon.ico ├── logo192.png ├── logo512.png ├── robots.txt ├── job-search (1).png ├── manifest.json └── index.html ├── src ├── Assets │ ├── images │ │ ├── flp.jpeg │ │ ├── ibm.jpeg │ │ ├── optum.png │ │ ├── paytm.png │ │ ├── sap.jpeg │ │ ├── tcs.webp │ │ ├── tesla.png │ │ ├── amazon.png │ │ ├── deloitte.png │ │ ├── facebook.png │ │ ├── infosys.png │ │ ├── myntra.png │ │ ├── naukri.png │ │ ├── oracle.png │ │ ├── synopsys.png │ │ ├── accenture.jpeg │ │ ├── cognizant.webp │ │ ├── flipkart.jpeg │ │ ├── cloud-mentor.jpeg │ │ ├── elastic-run.jpeg │ │ ├── tech-mahindra.png │ │ └── cool-background.png │ └── jobs.json ├── client.js ├── setupTests.js ├── index.css ├── index.js ├── components │ ├── ErrorPage │ │ ├── index.jsx │ │ └── index.css │ ├── Navbar │ │ ├── index.jsx │ │ └── index.css │ ├── Home │ │ ├── __test__ │ │ │ └── home.test.js │ │ ├── index.css │ │ └── index.jsx │ ├── Discussion │ │ ├── rating.jsx │ │ ├── reply.jsx │ │ ├── editor.jsx │ │ ├── __test__ │ │ │ └── discssion.test.js │ │ ├── commentCard.jsx │ │ ├── index.jsx │ │ └── index.css │ ├── SaveJobs │ │ └── index.jsx │ ├── ApplyJobs │ │ ├── index.jsx │ │ └── index.css │ ├── PostJob │ │ ├── index.css │ │ └── index.jsx │ ├── Filter │ │ ├── index.css │ │ └── index.jsx │ └── Jobs │ │ ├── index.css │ │ └── index.jsx ├── App.css └── App.js ├── .gitignore ├── package.json └── README.md /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Himanshu-25/job-portal/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Himanshu-25/job-portal/HEAD/public/logo192.png -------------------------------------------------------------------------------- /public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Himanshu-25/job-portal/HEAD/public/logo512.png -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /public/job-search (1).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Himanshu-25/job-portal/HEAD/public/job-search (1).png -------------------------------------------------------------------------------- /src/Assets/images/flp.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Himanshu-25/job-portal/HEAD/src/Assets/images/flp.jpeg -------------------------------------------------------------------------------- /src/Assets/images/ibm.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Himanshu-25/job-portal/HEAD/src/Assets/images/ibm.jpeg -------------------------------------------------------------------------------- /src/Assets/images/optum.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Himanshu-25/job-portal/HEAD/src/Assets/images/optum.png -------------------------------------------------------------------------------- /src/Assets/images/paytm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Himanshu-25/job-portal/HEAD/src/Assets/images/paytm.png -------------------------------------------------------------------------------- /src/Assets/images/sap.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Himanshu-25/job-portal/HEAD/src/Assets/images/sap.jpeg -------------------------------------------------------------------------------- /src/Assets/images/tcs.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Himanshu-25/job-portal/HEAD/src/Assets/images/tcs.webp -------------------------------------------------------------------------------- /src/Assets/images/tesla.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Himanshu-25/job-portal/HEAD/src/Assets/images/tesla.png -------------------------------------------------------------------------------- /src/Assets/images/amazon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Himanshu-25/job-portal/HEAD/src/Assets/images/amazon.png -------------------------------------------------------------------------------- /src/Assets/images/deloitte.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Himanshu-25/job-portal/HEAD/src/Assets/images/deloitte.png -------------------------------------------------------------------------------- /src/Assets/images/facebook.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Himanshu-25/job-portal/HEAD/src/Assets/images/facebook.png -------------------------------------------------------------------------------- /src/Assets/images/infosys.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Himanshu-25/job-portal/HEAD/src/Assets/images/infosys.png -------------------------------------------------------------------------------- /src/Assets/images/myntra.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Himanshu-25/job-portal/HEAD/src/Assets/images/myntra.png -------------------------------------------------------------------------------- /src/Assets/images/naukri.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Himanshu-25/job-portal/HEAD/src/Assets/images/naukri.png -------------------------------------------------------------------------------- /src/Assets/images/oracle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Himanshu-25/job-portal/HEAD/src/Assets/images/oracle.png -------------------------------------------------------------------------------- /src/Assets/images/synopsys.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Himanshu-25/job-portal/HEAD/src/Assets/images/synopsys.png -------------------------------------------------------------------------------- /src/Assets/images/accenture.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Himanshu-25/job-portal/HEAD/src/Assets/images/accenture.jpeg -------------------------------------------------------------------------------- /src/Assets/images/cognizant.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Himanshu-25/job-portal/HEAD/src/Assets/images/cognizant.webp -------------------------------------------------------------------------------- /src/Assets/images/flipkart.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Himanshu-25/job-portal/HEAD/src/Assets/images/flipkart.jpeg -------------------------------------------------------------------------------- /src/Assets/images/cloud-mentor.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Himanshu-25/job-portal/HEAD/src/Assets/images/cloud-mentor.jpeg -------------------------------------------------------------------------------- /src/Assets/images/elastic-run.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Himanshu-25/job-portal/HEAD/src/Assets/images/elastic-run.jpeg -------------------------------------------------------------------------------- /src/Assets/images/tech-mahindra.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Himanshu-25/job-portal/HEAD/src/Assets/images/tech-mahindra.png -------------------------------------------------------------------------------- /src/Assets/images/cool-background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Himanshu-25/job-portal/HEAD/src/Assets/images/cool-background.png -------------------------------------------------------------------------------- /src/client.js: -------------------------------------------------------------------------------- 1 | import sanityClient from "@sanity/client"; 2 | 3 | export default sanityClient({ 4 | projectId: `${process.env.REACT_APP_PROJECT_ID}`, 5 | dataset: `${process.env.REACT_APP_DATASET}`, 6 | useCdn: false, 7 | }); 8 | -------------------------------------------------------------------------------- /src/setupTests.js: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom'; 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | .env 8 | 9 | # testing 10 | /coverage 11 | 12 | # production 13 | /build 14 | 15 | # misc 16 | .DS_Store 17 | .env.local 18 | .env.development.local 19 | .env.test.local 20 | .env.production.local 21 | 22 | npm-debug.log* 23 | yarn-debug.log* 24 | yarn-error.log* 25 | -------------------------------------------------------------------------------- /src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 12 | monospace; 13 | } 14 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom/client'; 3 | import './index.css'; 4 | import App from './App'; 5 | 6 | const root = ReactDOM.createRoot(document.getElementById('root')); 7 | root.render( 8 | 9 | 10 | 11 | ); 12 | 13 | // If you want to start measuring performance in your app, pass a function 14 | // to log results (for example: reportWebVitals(console.log)) 15 | // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals 16 | -------------------------------------------------------------------------------- /public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /src/components/ErrorPage/index.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import './index.css'; 3 | import { Link } from 'react-router-dom'; 4 | 5 | const ErrorPage = () => { 6 | return ( 7 | <> 8 |
9 |
404
10 |
11 |
12 | File not found 13 | 404-error 18 |
19 | Go To Home 20 |
21 |
22 | 23 | ); 24 | } 25 | 26 | export default ErrorPage; 27 | -------------------------------------------------------------------------------- /src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | height: 40vmin; 7 | pointer-events: none; 8 | } 9 | 10 | @media (prefers-reduced-motion: no-preference) { 11 | .App-logo { 12 | animation: App-logo-spin infinite 20s linear; 13 | } 14 | } 15 | 16 | .App-header { 17 | background-color: #282c34; 18 | min-height: 100vh; 19 | display: flex; 20 | flex-direction: column; 21 | align-items: center; 22 | justify-content: center; 23 | font-size: calc(10px + 2vmin); 24 | color: white; 25 | } 26 | 27 | .App-link { 28 | color: #61dafb; 29 | } 30 | 31 | @keyframes App-logo-spin { 32 | from { 33 | transform: rotate(0deg); 34 | } 35 | to { 36 | transform: rotate(360deg); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/components/Navbar/index.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { Link } from "react-router-dom"; 3 | import "./index.css"; 4 | 5 | const Navbar = () => { 6 | return ( 7 | <> 8 |
9 | 29 |
30 | 31 | ); 32 | }; 33 | 34 | export default Navbar; 35 | -------------------------------------------------------------------------------- /src/components/Home/__test__/home.test.js: -------------------------------------------------------------------------------- 1 | import { render , screen , cleanup } from '@testing-library/react' 2 | import Home from '..'; 3 | import { BrowserRouter, Route } from "react-router-dom"; 4 | 5 | const MockHome = ()=> { 6 | return 7 | 8 | ; 9 | } 10 | test('should render Heading in home component',()=>{ 11 | render( 12 | 13 | ); 14 | const heading = screen.getByRole("heading",{level:3}) 15 | expect(heading).toBeInTheDocument() 16 | }) 17 | 18 | test('should render button in Home component',()=>{ 19 | render(); 20 | const button = screen.getByTestId("btn") 21 | expect(button).toBeInTheDocument() 22 | }) 23 | test("should render social media images", () => { 24 | render(); 25 | const images = screen.getByTestId("images"); 26 | expect(images).toBeInTheDocument(); 27 | }); -------------------------------------------------------------------------------- /src/components/Discussion/rating.jsx: -------------------------------------------------------------------------------- 1 | import React, { useState } from "react"; 2 | import "./index.css"; 3 | const StarRating = ({ onChange }) => { 4 | const [rating, setRating] = useState(0); 5 | const [hover, setHover] = useState(0); 6 | function handleMouseLeave() { 7 | setHover(rating); 8 | onChange(rating); 9 | } 10 | return ( 11 |
12 | {[...Array(5)].map((star, index) => { 13 | index += 1; 14 | return ( 15 | 29 | ); 30 | })} 31 |
32 | ); 33 | }; 34 | export default StarRating; 35 | -------------------------------------------------------------------------------- /src/App.js: -------------------------------------------------------------------------------- 1 | import './App.css'; 2 | import Home from './components/Home'; 3 | import Jobs from './components/Jobs'; 4 | import { BrowserRouter, Routes, Route } from "react-router-dom"; 5 | import PostJob from './components/PostJob'; 6 | import SaveJobs from './components/SaveJobs'; 7 | import Discussion from './components/Discussion'; 8 | import ErrorPage from './components/ErrorPage'; 9 | import ApplyJobs from './components/ApplyJobs'; 10 | 11 | function App() { 12 | return ( 13 | <> 14 | 15 | 16 | 17 | } /> 18 | } /> 19 | } /> 20 | } /> 21 | } /> 22 | } /> 23 | } /> 24 | } /> 25 | 26 | 27 | 28 | 29 | ); 30 | } 31 | 32 | export default App; 33 | -------------------------------------------------------------------------------- /src/components/Home/index.css: -------------------------------------------------------------------------------- 1 | .title { 2 | font-size: 45px; 3 | display: flex; 4 | justify-content: center; 5 | flex-direction: column; 6 | } 7 | .title > h3 { 8 | text-align: center; 9 | color: #fff; 10 | font-weight: bold; 11 | margin-bottom: 20px; 12 | } 13 | span { 14 | color: #f7cc53; 15 | } 16 | .button { 17 | text-align: center; 18 | display: flex; 19 | flex-direction: column; 20 | } 21 | .button a { 22 | flex-direction: column; 23 | text-decoration: none; 24 | border: 2px solid #f7cc53; 25 | border-radius: 20px; 26 | padding: 20px; 27 | text-transform: uppercase; 28 | color: #fff; 29 | font-weight: bold; 30 | } 31 | .button a:hover { 32 | background: #f7cc53; 33 | transition: 1.2s ease; 34 | color: black; 35 | border: 2px solid #fff; 36 | } 37 | .small-tagline { 38 | font-size: 20px; 39 | display: flex; 40 | justify-content: center; 41 | flex-direction: column; 42 | text-align: center; 43 | } 44 | .small-tagline p { 45 | color: #fff; 46 | top: 50%; 47 | opacity: 0.7; 48 | margin-bottom: 30px; 49 | } 50 | .social-media { 51 | display: flex; 52 | justify-content: center; 53 | gap: 20px; 54 | } 55 | .social-media > img { 56 | width: 70px; 57 | } 58 | @media (max-width: 640px){ 59 | .title{ 60 | font-size: 25px; 61 | } 62 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "job-portal", 3 | "version": "0.1.0", 4 | "homepage": "https://Himanshur25.github.io/job-portal", 5 | "private": true, 6 | "dependencies": { 7 | "@sanity/client": "^4.0.1", 8 | "@testing-library/jest-dom": "^5.16.5", 9 | "@testing-library/react": "^13.4.0", 10 | "@testing-library/user-event": "^13.5.0", 11 | "axios": "^1.2.3", 12 | "html-react-parser": "^3.0.6", 13 | "jest-worker": "^29.4.1", 14 | "react": "^18.2.0", 15 | "react-dom": "^18.2.0", 16 | "react-icons": "^4.7.1", 17 | "react-router-dom": "^6.7.0", 18 | "react-scripts": "5.0.1", 19 | "react-spinners": "^0.13.8", 20 | "web-vitals": "^2.1.4" 21 | }, 22 | "scripts": { 23 | "start": "react-scripts start", 24 | "build": "react-scripts build", 25 | "test": "react-scripts test --transformIgnorePatterns \"node_modules/(?!axios)/\"", 26 | "eject": "react-scripts eject", 27 | "predeploy": "npm run build", 28 | "deploy": "gh-pages -d build" 29 | }, 30 | "eslintConfig": { 31 | "extends": [ 32 | "react-app", 33 | "react-app/jest" 34 | ] 35 | }, 36 | "browserslist": { 37 | "production": [ 38 | ">0.2%", 39 | "not dead", 40 | "not op_mini all" 41 | ], 42 | "development": [ 43 | "last 1 chrome version", 44 | "last 1 firefox version", 45 | "last 1 safari version" 46 | ] 47 | }, 48 | "devDependencies": { 49 | "gh-pages": "^6.0.0" 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/components/Home/index.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import Navbar from "../Navbar"; 3 | import { Link } from "react-router-dom"; 4 | import "./index.css"; 5 | 6 | const Home = () => { 7 | return ( 8 | <> 9 | 10 |
11 |
12 |

13 | Find the Right Job In the 14 |
15 | Right Companies 16 |

17 |
18 |

Got fired..!! Get Ready to be hired

19 |
20 |
21 |
22 | Browse Jobs 23 |
24 |
25 |
26 | fb 27 | google 28 | youtube 29 | linkedin 30 |
31 | 32 | ); 33 | }; 34 | 35 | export default Home; 36 | -------------------------------------------------------------------------------- /src/components/Navbar/index.css: -------------------------------------------------------------------------------- 1 | 2 | *{ 3 | margin: 0; 4 | padding: 0; 5 | font-family: 'poppins'; 6 | } 7 | 8 | .banner-img{ 9 | background:url("../../Assets/images/cool-background.png"); 10 | height: 700px; 11 | background-size: cover; 12 | background-repeat: no-repeat; 13 | -webkit-clip-path: polygon(100% 0, 100% 90%, 0 95%, 0 0); 14 | clip-path: polygon(100% 0, 100% 90%, 0 95%, 0 0); 15 | display: flex; 16 | flex-direction: column; 17 | align-items: center; 18 | justify-content: center; 19 | 20 | } 21 | #navbar { 22 | display: flex; 23 | justify-content: space-between; 24 | background: #fff; 25 | color: #000; 26 | padding: 1.1rem; 27 | position: sticky; 28 | } 29 | 30 | #navbar ul { 31 | display: flex; 32 | align-items: center; 33 | list-style: none; 34 | } 35 | 36 | #navbar ul li a { 37 | color: #000; 38 | text-decoration: none; 39 | padding: 0.75rem 1.5rem; 40 | color: #0000; 41 | font-weight: bold; 42 | background: linear-gradient(90deg,#6B5DF2 50%,#000 0) var(--_p,100%)/200% no-repeat; 43 | -webkit-background-clip: text; 44 | background-clip: text; 45 | transition: 1s; 46 | } 47 | #navbar ul li a:hover { 48 | --_p: 0%; 49 | } 50 | .logo >span{ 51 | color: #f7cc53; 52 | } 53 | @media (max-width: 640px) { 54 | #navbar { 55 | flex-direction: column; 56 | align-items: center; 57 | } 58 | 59 | #navbar .logo { 60 | margin-bottom: 0.5rem; 61 | text-align: center; 62 | } 63 | 64 | #navbar ul { 65 | padding: 0.5rem; 66 | } 67 | #navbar ul li a { 68 | padding: 0.5rem; 69 | } 70 | } 71 | 72 | 73 | -------------------------------------------------------------------------------- /src/components/SaveJobs/index.jsx: -------------------------------------------------------------------------------- 1 | import React, { useState } from "react"; 2 | import Navbar from "../Navbar"; 3 | 4 | const SaveJobs = () => { 5 | const jobs = [JSON.parse(localStorage.getItem("Job"))]; 6 | return ( 7 |
8 | 9 |
10 |
11 |
12 |

Saved Jobs

13 |
14 |
15 |
16 |
17 | {jobs.map(({ logo, company, position, location, role }) => { 18 | return ( 19 |
20 |
21 |
22 | logo 27 |
28 |

{company}

29 |

{position}

30 |
31 |

{location}

32 |

{role}

33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 | ); 41 | })} 42 |
43 |
44 |
45 |
46 | ); 47 | }; 48 | 49 | export default SaveJobs; 50 | -------------------------------------------------------------------------------- /src/components/ApplyJobs/index.jsx: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react'; 2 | import './index.css'; 3 | import { useNavigate } from 'react-router-dom'; 4 | 5 | const ApplyJobs = () => { 6 | const navigate=useNavigate(); 7 | const [name,setName]=useState("") 8 | const OnformSubmit=()=>{ 9 | if(name==="" ){ 10 | alert("Please fill the name first") 11 | } 12 | else{ 13 | alert("Your Job Application has been Applied Successfully") 14 | navigate("/Jobs") 15 | 16 | } 17 | } 18 | return ( 19 |
20 |
21 |
22 |

Fill the form

23 |
24 |
25 |
26 | 29 | setName(e.target.value)} 36 | required 37 | /> 38 |
39 |
40 | 43 | 46 |
47 |
48 | 55 |
56 |
57 |
58 |
59 | ); 60 | } 61 | 62 | export default ApplyJobs; 63 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ONLINE JOB PORTAL USING REACT AND SANITY 2 | 3 | 4 | This website is all about searching the top jobs from top-reputed companies all over the world. 5 | It has additional functionalities of searching and filter jobs on based of their job role or experience. 6 | Further more it has a form where a company user who wants to add their job on to our site can fill the form and add it. 7 | Next, it has an option where a student/user can save the job by clicking on bookmark icon. 8 | 9 | 10 | Now one surprise section added is of discussion Chamber which is connected with Sanity(Headless CMS). 11 | A text-editor is added with functionalities of bold,italic,etc and image section where a user can just upload an image or can copy any image address from wherever and it will automatically preview image according to the type of input url using regex. 12 | User can reply the same thing as well at the same time. 13 | 14 | This website is fully responsive.. 15 | 16 | 17 | 18 | 19 | Home Page 20 | 21 | ![Screenshot 2023-01-28 at 8 49 15 PM](https://user-images.githubusercontent.com/114575434/215274848-ce9787c7-8bdc-43c5-9f58-f7862b4cecd7.png) 22 | 23 | 24 | Jobs Page 25 | 26 | ![Screenshot 2023-01-28 at 8 47 22 PM](https://user-images.githubusercontent.com/114575434/215274857-f2aefecd-f349-4c8c-b703-0c4ad410159a.png) 27 | 28 | 29 | 30 | Job Category Filter 31 | 32 | 33 | ![Screenshot 2023-01-28 at 8 47 22 PM](https://user-images.githubusercontent.com/114575434/215274869-908a1630-83c9-44c6-bf37-dfb76262a895.png) 34 | 35 | 36 | 37 | Discussion Chamber 38 | 39 | ![Screenshot 2023-01-28 at 8 52 19 PM](https://user-images.githubusercontent.com/114575434/215274887-06fa1c2e-79b1-47f0-b0ee-bdb34d6f1281.png) 40 | 41 | 42 | 43 | 44 | 45 | Tools and Technology Used:- 46 | 47 | 1.HTML CSS AND JS 48 | 2.React JS 49 | 3.Sanity for Backend. 50 | 4.VS Code 51 | 5.Vercel for deployment. 52 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 17 | 18 | 19 | 28 | React App 29 | 30 | 31 | 32 |
33 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /src/components/PostJob/index.css: -------------------------------------------------------------------------------- 1 | h1 { 2 | font-weight: 400; 3 | line-height: 1.2; 4 | } 5 | p { 6 | font-size: 1.125rem; 7 | } 8 | h1, 9 | p { 10 | margin-top: 0; 11 | margin-bottom: 0.5rem; 12 | } 13 | 14 | label { 15 | display: flex; 16 | align-items: center; 17 | font-size: 1.125rem; 18 | margin-bottom: 0.5rem; 19 | } 20 | button { 21 | border: none; 22 | } 23 | .container { 24 | width: 100%; 25 | margin: 3.125rem auto 0 auto; 26 | } 27 | @media (min-width: 576px) { 28 | .container { 29 | max-width: 540px; 30 | } 31 | } 32 | 33 | @media (min-width: 768px) { 34 | .container { 35 | max-width: 720px; 36 | } 37 | } 38 | .header { 39 | padding: 0 0.625rem; 40 | margin-bottom: 1.875rem; 41 | } 42 | .description { 43 | font-style: italic; 44 | font-weight: 200; 45 | text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.4); 46 | } 47 | .post-job { 48 | text-align: center; 49 | } 50 | 51 | form { 52 | background: #f9f9f9; 53 | padding: 2.5rem 0.625rem; 54 | border-radius: 0.25rem; 55 | } 56 | 57 | @media (min-width: 480px) { 58 | form { 59 | padding: 2.5rem; 60 | } 61 | } 62 | 63 | .form-group { 64 | margin: 0 auto 1.25rem auto; 65 | padding: 0.25rem; 66 | } 67 | 68 | .form-control { 69 | box-sizing: border-box; 70 | width: 100%; 71 | height: 2.375rem; 72 | padding: 0.375rem 0.75rem; 73 | } 74 | 75 | .form-control:focus { 76 | border-color: 70bdgg; 77 | outline: 0; 78 | box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25); 79 | } 80 | .input-radio{ 81 | display: inline-block; 82 | margin-right: 0.625rem; 83 | min-height: 1.25rem; 84 | min-width: 1.25rem; 85 | } 86 | 87 | .input-textarea { 88 | min-height: 120px; 89 | width: 70%; 90 | padding: 0.625rem; 91 | resize: vertical; 92 | } 93 | 94 | .submit-button { 95 | display: block; 96 | width: 100%; 97 | padding: 0.75rem; 98 | background: Green; 99 | color: White; 100 | border-radius: 2px; 101 | cursor: pointer; 102 | } 103 | -------------------------------------------------------------------------------- /src/components/Filter/index.css: -------------------------------------------------------------------------------- 1 | .job-filter{ 2 | display: flex; 3 | flex-direction: column; 4 | } 5 | .job-search{ 6 | display: flex; 7 | } 8 | .search-box{ 9 | margin: 25px 10px 0px 5px; 10 | padding:5px; 11 | font-size: 19px; 12 | } 13 | .job-search{ 14 | margin-top: 10px; 15 | } 16 | .search-term{ 17 | padding: 10px; 18 | width: 180px; 19 | } 20 | .job-category{ 21 | margin-top: 39px; 22 | font-size: 20px; 23 | background-color: #fff; 24 | padding: 20px; 25 | border-radius: 20px; 26 | box-shadow: #091e5a; 27 | } 28 | .job-category>ul{ 29 | list-style: none; 30 | padding: 8px; 31 | cursor: pointer; 32 | } 33 | .job-category ul >li{ 34 | opacity: 0.8; 35 | margin-top: 10px; 36 | display: flex; 37 | gap: 4px; 38 | } 39 | .job-category ul >li:hover{ 40 | color: blue; 41 | transform: scale(1.02); 42 | transition: 200ms ease; 43 | } 44 | .filter-page{ 45 | font-size: 30px; 46 | } 47 | @media (max-width:855px) 48 | { 49 | .search-box{ 50 | font-size: 8px; 51 | } 52 | .job-category{ 53 | font-size: 10px; 54 | } 55 | .job-category ul >li{ 56 | font-size: 10px; 57 | display: flex; 58 | gap: 4px; 59 | } 60 | .search-term{ 61 | padding: 2px; 62 | } 63 | } 64 | @media (max-width:640px){ 65 | .job-card{ 66 | display: flex; 67 | flex-wrap: wrap; 68 | width: 108%; 69 | } 70 | .job-section{ 71 | flex-direction: column-reverse; 72 | } 73 | .job-search{ 74 | display: flex; 75 | justify-content: center; 76 | } 77 | .search-term{ 78 | padding: 1px; 79 | width: 100px; 80 | } 81 | .search{ 82 | display: flex; 83 | flex-direction: column; 84 | justify-content: center; 85 | margin-left: 2px; 86 | } 87 | ::placeholder{ 88 | font-size: 10px; 89 | } 90 | .job-button{ 91 | display: flex; 92 | } 93 | .filter{ 94 | display: flex; 95 | justify-content: center; 96 | gap: 50px; 97 | } 98 | .job-category{ 99 | width: 100px; 100 | } 101 | .search>h3{ 102 | text-align: center; 103 | font-size: 10px; 104 | } 105 | .job-detail{ 106 | width: 180px; 107 | } 108 | } -------------------------------------------------------------------------------- /src/components/Discussion/reply.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { useState, useRef } from "react"; 3 | import "./index.css"; 4 | import Editor from "./editor"; 5 | import { BiUserCircle } from "react-icons/bi"; 6 | 7 | const Reply = ({ onAdd }) => { 8 | const [comment, setComment] = useState(""); 9 | const [name, setName] = useState(""); 10 | const [imageUrl, setImageUrl] = useState(""); 11 | const commentRef = useRef(); 12 | const handleNameChange = (e) => { 13 | setName(e.target.value); 14 | }; 15 | const handleCommentChange = (e) => { 16 | setComment(e.target.value); 17 | }; 18 | 19 | return ( 20 |
21 |
22 |
23 |
24 |
25 |
26 | 27 |
28 | 35 |
36 |
37 |
38 |
39 |
48 |
49 | 50 | 51 | 57 |
58 |
59 | {imageUrl && ( 60 | 61 | )} 62 |
63 |
64 | 65 |
66 | ); 67 | }; 68 | 69 | export default Reply; 70 | -------------------------------------------------------------------------------- /src/components/ApplyJobs/index.css: -------------------------------------------------------------------------------- 1 | h1 { 2 | font-weight: 400; 3 | line-height: 1.2; 4 | } 5 | p { 6 | font-size: 1.125rem; 7 | } 8 | h1, 9 | p { 10 | margin-top: 0; 11 | margin-bottom: 0.5rem; 12 | } 13 | 14 | label { 15 | display: flex; 16 | align-items: center; 17 | font-size: 1.125rem; 18 | margin-bottom: 0.5rem; 19 | } 20 | button { 21 | border: none; 22 | } 23 | .container { 24 | width: 100%; 25 | margin: 3.125rem auto 0 auto; 26 | display: flex; 27 | flex-direction: column; 28 | justify-content: center; 29 | align-items: center; 30 | } 31 | @media (min-width: 576px) { 32 | .container { 33 | max-width: 540px; 34 | } 35 | } 36 | 37 | @media (min-width: 768px) { 38 | .container { 39 | max-width: 720px; 40 | } 41 | } 42 | .header { 43 | padding: 0 0.625rem; 44 | margin-bottom: 1.875rem; 45 | } 46 | .description { 47 | font-style: italic; 48 | font-weight: 200; 49 | text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.4); 50 | } 51 | .post-job { 52 | text-align: center; 53 | } 54 | 55 | form { 56 | background: #f9f9f9; 57 | padding: 2.5rem 0.625rem; 58 | border-radius: 0.25rem; 59 | } 60 | 61 | @media (min-width: 480px) { 62 | form { 63 | padding: 2.5rem; 64 | } 65 | } 66 | 67 | .form-group { 68 | margin: 0 auto 1.25rem auto; 69 | padding: 0.25rem; 70 | } 71 | 72 | .form-control { 73 | display: block; 74 | width: 100%; 75 | height: 2.375rem; 76 | padding: 0.375rem 0.75rem; 77 | color: #495057; 78 | background-color: #fff; 79 | background-clip: padding-box; 80 | border: 1px solid #ced4da; 81 | border-radius: 0.25rem; 82 | transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; 83 | } 84 | 85 | .form-control:focus { 86 | border-color: 70bdgg; 87 | outline: 0; 88 | box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25); 89 | } 90 | .input-radio{ 91 | display: inline-block; 92 | margin-right: 0.625rem; 93 | min-height: 1.25rem; 94 | min-width: 1.25rem; 95 | } 96 | 97 | .input-textarea { 98 | min-height: 120px; 99 | width: 100%; 100 | padding: 0.625rem; 101 | resize: vertical; 102 | } 103 | 104 | .submit-button { 105 | display: block; 106 | width: 100%; 107 | padding: 0.75rem; 108 | background: Green; 109 | color: White; 110 | border-radius: 2px; 111 | cursor: pointer; 112 | } -------------------------------------------------------------------------------- /src/components/Jobs/index.css: -------------------------------------------------------------------------------- 1 | .job-list { 2 | margin: 1%; 3 | padding: 0.7rem; 4 | background-color: #f9f9f9; 5 | } 6 | .job-card { 7 | display: flex; 8 | justify-content: space-between; 9 | padding: 1.4rem; 10 | min-height: 100px; 11 | align-items: center; 12 | background-color: #fff; 13 | 14 | } 15 | .job-card:hover { 16 | box-shadow: 1px 2px 5px 5px rgba(222,217,217,0.75); 17 | -webkit-box-shadow: 1px 2px 5px 5px rgba(222,217,217,0.75); 18 | -moz-box-shadow: 1px 2px 5px 5px rgba(222,217,217,0.75); 19 | transition: 70ms ease; 20 | transform: scale(1.02); 21 | } 22 | 23 | .job-name { 24 | display: flex; 25 | } 26 | .job-profile { 27 | width: 60px; 28 | height: 60px; 29 | margin: 0.5rem; 30 | } 31 | .job-detail { 32 | padding: 0px 10px; 33 | } 34 | .job-detail > h4 { 35 | color: #1945f5; 36 | font-size: 1rem; 37 | text-transform: uppercase; 38 | } 39 | .job-detail > h3 { 40 | color: #091e5a; 41 | font-size: 1.3rem; 42 | margin-bottom: 15px; 43 | } 44 | .job-detail > p { 45 | display: -webkit-box; 46 | overflow: hidden; 47 | -webkit-line-clamp: 2; 48 | -webkit-box-orient: vertical; 49 | } 50 | .job-posted { 51 | font-size: 0.8rem; 52 | } 53 | .job-posting { 54 | text-decoration: none; 55 | color: white; 56 | font-weight: bold; 57 | background-color: #4fb075; 58 | display: flex; 59 | gap: 10px; 60 | padding: 10px; 61 | } 62 | .job-posting >a:hover{ 63 | background-color: #1945f5; 64 | transition: 400ms ease-in-out; 65 | } 66 | .category { 67 | display: flex; 68 | gap: 22px; 69 | } 70 | .job-background { 71 | background: #6b5df2; 72 | height: 270px; 73 | -webkit-clip-path: polygon(100% 0, 100% 81%, 50% 90%, 0 83%, 0 0); 74 | clip-path: polygon(100% 0, 100% 81%, 50% 90%, 0 83%, 0 0); 75 | } 76 | .job-background .title { 77 | display: flex; 78 | align-items: center; 79 | color: white; 80 | font-size: 35px; 81 | padding: 80px 0px; 82 | } 83 | .job-section{ 84 | display: flex; 85 | background: #F7F7FB; 86 | max-width: 100%; 87 | } 88 | .jobs-for-you{ 89 | width: 100%; 90 | } 91 | .job-page{ 92 | width:82%; 93 | } 94 | @media (max-width:855px) 95 | { 96 | .job-page{ 97 | font-size: 10px; 98 | 99 | } 100 | .job-card{ 101 | display: flex; 102 | } 103 | .job-detail>h4 { 104 | font-size: 11px; 105 | } 106 | .job-detail>h3{ 107 | font-size: 15px; 108 | }.category>p{ 109 | font-size: 10px; 110 | flex-wrap: wrap; 111 | } 112 | } 113 | .save-button{ 114 | font-size: 22px; 115 | } 116 | .job-button{ 117 | display: flex; 118 | align-items: center; 119 | gap: 30px; 120 | } 121 | -------------------------------------------------------------------------------- /src/components/Discussion/editor.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { useState } from "react"; 3 | import axios from "axios"; 4 | import { 5 | ImBold, 6 | ImItalic, 7 | ImUnderline, 8 | ImImage, 9 | ImQuotesLeft, 10 | } from "react-icons/im"; 11 | import { SyncLoader } from "react-spinners"; 12 | 13 | const Editor = ({ onUrlChange, commentRef }) => { 14 | const [spinner, setSpinner] = useState(false); 15 | 16 | function uploadImage(event) { 17 | const fileToUpload = event.target.files[0]; 18 | setSpinner(true); 19 | 20 | var formData = new FormData(); 21 | formData.append("file", fileToUpload); 22 | formData.append("api_key", "316255361857537"); 23 | formData.append("upload_preset", "i74l2yd4"); 24 | 25 | axios 26 | .post( 27 | "https://api.cloudinary.com/v1_1/ddmtjxz7e/image/upload", 28 | formData, 29 | { 30 | headers: { 31 | "Content-Type": "multipart/form-data", 32 | }, 33 | } 34 | ) 35 | .then((res) => { 36 | const imageUrl = res.data.secure_url; 37 | onUrlChange((prev) => [...prev, imageUrl]); 38 | commentRef.current.innerText += imageUrl; 39 | setSpinner(false); 40 | }); 41 | } 42 | 43 | function textActions(textStyle) { 44 | let styleTag = document.createElement(textStyle); 45 | if (window.getSelection) { 46 | var rangeSelection = window.getSelection(); 47 | if (rangeSelection.rangeCount) { 48 | var range = rangeSelection.getRangeAt(0).cloneRange(); 49 | range.surroundContents(styleTag); 50 | rangeSelection.removeAllRanges(); 51 | rangeSelection.addRange(range); 52 | } 53 | } 54 | } 55 | 56 | return ( 57 | <> 58 |
59 | 62 | 69 | 76 | 77 | 86 | {spinner && ( 87 |

88 | 89 |

90 | )} 91 | 94 | 101 |
102 | 103 | ); 104 | }; 105 | 106 | export default Editor; 107 | -------------------------------------------------------------------------------- /src/components/Filter/index.jsx: -------------------------------------------------------------------------------- 1 | import { useState } from "react"; 2 | import "./index.css"; 3 | const experience = [ 4 | { min: 0, max: 1 }, 5 | { min: 2, max: 3 }, 6 | { min: 4, max: 5 }, 7 | { min: 5, max: 10 }, 8 | ]; 9 | 10 | const Filter = ({ 11 | setFilteredJobs, 12 | handleJobFilter, 13 | handleExperienceFilter, 14 | searchEvent, 15 | }) => { 16 | const [checkedState, setCheckedState] = useState( 17 | new Array(experience.length).fill(false) 18 | ); 19 | 20 | const handleOnChange = (position) => { 21 | const updatedCheckedState = checkedState.map((item, index) => 22 | index === position ? !item : item 23 | ); 24 | 25 | setCheckedState(updatedCheckedState); 26 | handleExperienceFilter(updatedCheckedState); 27 | }; 28 | return ( 29 | <> 30 |
31 |
32 |
33 |

Search Jobs

34 |
35 | 41 |
42 |
43 |
44 |
45 |

Categories

46 |
    47 |
  • Frontend
  • 48 |
  • Backend
  • 49 |
  • Devops
  • 50 |
  • Full Stack
  • 51 |
  • Digital Marketing
  • 52 |
53 |
54 | 55 |
56 |

Experience

57 |
    58 |
  • 59 | handleOnChange(0)} 64 | /> 65 | 0-1 year 66 |
  • 67 |
  • 68 | handleOnChange(1)} 73 | /> 74 | 2-3 year 75 |
  • 76 |
  • 77 | handleOnChange(2)} 82 | /> 83 | 4-5 year 84 |
  • 85 |
  • 86 | handleOnChange(3)} 91 | /> 92 | 5+ year 93 |
  • 94 |
95 |
96 |
97 |
98 |
99 | 100 | ); 101 | }; 102 | 103 | export default Filter; 104 | -------------------------------------------------------------------------------- /src/components/ErrorPage/index.css: -------------------------------------------------------------------------------- 1 | 2 | 3 | .error-page { 4 | background: radial-gradient(#000, #111); 5 | color: white; 6 | overflow: hidden; 7 | /* height: 100%; */ 8 | height: 840px; 9 | user-select: none; 10 | } 11 | 12 | .static { 13 | width: 100%; 14 | height: 100%; 15 | position: relative; 16 | margin: 0; 17 | padding: 0; 18 | top: -100px; 19 | opacity: 0.05; 20 | z-index: 230; 21 | user-select: none; 22 | -webkit-user-drag: none; 23 | } 24 | 25 | .error { 26 | text-align: center; 27 | /* font-family: 'Gilda Display', serif; */ 28 | font-size: 95px; 29 | font-style: italic; 30 | text-align: center; 31 | width: 100px; 32 | height: 60px; 33 | line-height: 60px; 34 | margin: auto; 35 | position: absolute; 36 | top: 0; 37 | bottom: 0; 38 | left: -60px; 39 | right: 0; 40 | animation: noise 2s linear infinite; 41 | overflow: default; 42 | } 43 | 44 | .error:after { 45 | content: '404'; 46 | /* font-family: 'Gilda Display', serif; */ 47 | font-size: 100px; 48 | font-style: italic; 49 | text-align: center; 50 | width: 150px; 51 | height: 60px; 52 | line-height: 60px; 53 | margin: auto; 54 | position: absolute; 55 | top: 0; 56 | bottom: 0; 57 | left: 0; 58 | right: 0; 59 | opacity: 0; 60 | color: blue; 61 | animation: noise-1 .2s linear infinite; 62 | } 63 | 64 | .info { 65 | text-align: center; 66 | /* font-family: 'Gilda Display', serif; */ 67 | font-size: 15px; 68 | font-style: italic; 69 | text-align: center; 70 | width: 200px; 71 | height: 60px; 72 | line-height: 60px; 73 | margin: auto; 74 | position: absolute; 75 | top: 140px; 76 | bottom: 0; 77 | left: 0; 78 | right: 0; 79 | animation: noise-3 1s linear infinite; 80 | } 81 | .home-button{ 82 | text-align: center; 83 | /* font-family: 'Gilda Display', serif; */ 84 | font-size: 15px; 85 | font-style: italic; 86 | text-align: center; 87 | width: 200px; 88 | height: 60px; 89 | line-height: 60px; 90 | margin: auto; 91 | position: absolute; 92 | top: 290px; 93 | bottom: 0; 94 | left: 4px; 95 | right: 0; 96 | 97 | } 98 | .home-button>a{ 99 | text-decoration: none; 100 | color: yellow; 101 | /* display: block; */ 102 | border: 1px solid yellow; 103 | padding: 10px; 104 | } 105 | .home-button>a:hover{ 106 | 107 | color: black; 108 | /* display: block; */ 109 | /* border: 1px solid yellow; */ 110 | padding: 10px; 111 | background-color: yellow; 112 | } 113 | 114 | .error:before { 115 | content: '404'; 116 | font-family: 'Gilda Display', serif; 117 | font-size: 100px; 118 | font-style: italic; 119 | text-align: center; 120 | width: 100px; 121 | height: 60px; 122 | line-height: 60px; 123 | margin: auto; 124 | position: absolute; 125 | top: 0; 126 | bottom: 0; 127 | left: 0; 128 | right: 0; 129 | opacity: 0; 130 | color: red; 131 | animation: noise-2 .2s linear infinite; 132 | } 133 | 134 | @keyframes noise-1 { 135 | 0%, 20%, 40%, 60%, 70%, 90% {opacity: 0;} 136 | 10% {opacity: .1;} 137 | 50% {opacity: .5; left: -6px;} 138 | 80% {opacity: .3;} 139 | 100% {opacity: .6; left: 2px;} 140 | } 141 | 142 | @keyframes noise-2 { 143 | 0%, 20%, 40%, 60%, 70%, 90% {opacity: 0;} 144 | 10% {opacity: .1;} 145 | 50% {opacity: .5; left: 6px;} 146 | 80% {opacity: .3;} 147 | 100% {opacity: .6; left: -2px;} 148 | } 149 | 150 | @keyframes noise { 151 | 0%, 3%, 5%, 42%, 44%, 100% {opacity: 1; transform: scaleY(1);} 152 | 4.3% {opacity: 1; transform: scaleY(1.7);} 153 | 43% {opacity: 1; transform: scaleX(1.5);} 154 | } 155 | 156 | @keyframes noise-3 { 157 | 0%,3%,5%,42%,44%,100% {opacity: 1; transform: scaleY(1);} 158 | 4.3% {opacity: 1; transform: scaleY(4);} 159 | 43% {opacity: 1; transform: scaleX(10) rotate(60deg);} 160 | } -------------------------------------------------------------------------------- /src/components/Discussion/__test__/discssion.test.js: -------------------------------------------------------------------------------- 1 | import { fireEvent, render, screen } from "@testing-library/react"; 2 | import { BrowserRouter } from "react-router-dom"; 3 | import CommentCard from "../commentCard"; 4 | import Editor from "../editor"; 5 | import DiscussionForm from "../index"; 6 | import userEvent from "@testing-library/user-event"; 7 | 8 | jest.spyOn(window, "alert").mockImplementation(() => {}); 9 | 10 | const MockComment = ({ deleteComment }) => { 11 | const commentValue = { 12 | _id: "syPd8qVyCPoQD7dljzzFdA", 13 | name: "Himanshu", 14 | rating: "0", 15 | content: "https://www.w3schools.com/css/img_lights.jpg\nHello", 16 | }; 17 | return ( 18 | 19 | 20 | 21 | ); 22 | }; 23 | const MockDiscussion = () => { 24 | return ( 25 | 26 | 27 | 28 | ); 29 | }; 30 | 31 | describe("Test the CommentCard component", () => { 32 | test("Should render CommentCard correctly", () => { 33 | render(); 34 | const name = screen.getByTestId("names"); 35 | const comment = screen.getByTestId("comments"); 36 | const rating = screen.getByTestId("ratings"); 37 | expect(name).toBeInTheDocument(); 38 | expect(comment).toBeInTheDocument(); 39 | expect(rating).toBeInTheDocument(); 40 | }); 41 | test("Toggle button should work properly", () => { 42 | const { getByTestId } = render(); 43 | const toggleButton = getByTestId("toggle-btn"); 44 | const comment = getByTestId("comments"); 45 | expect(toggleButton).toHaveTextContent("-"); 46 | fireEvent.click(toggleButton); 47 | expect(toggleButton).toHaveTextContent("+"); 48 | expect(comment).not.toBeVisible(); 49 | }); 50 | test("Delete button should be called one time", () => { 51 | const deleteComment = jest.fn(); 52 | const { queryByRole } = render( 53 | 54 | ); 55 | const deleteButton = queryByRole("delete"); 56 | fireEvent.click(deleteButton); 57 | expect(deleteComment).toHaveBeenCalledTimes(1); 58 | }); 59 | }); 60 | 61 | describe("Test the Editor Component", () => { 62 | test("Should check that the editor component has 4 Text style buttons", () => { 63 | render(); 64 | const buttonList = screen.getAllByRole("button"); 65 | expect(buttonList).toHaveLength(4); 66 | }); 67 | test("upload image file only", () => { 68 | const file = new File(["accenture"], "accenture.jpeg", { 69 | type: "image/jpeg", 70 | }); 71 | render(); 72 | const input = screen.getByTestId("image-upload"); 73 | userEvent.upload(input, file); 74 | 75 | expect(input.files[0]).toStrictEqual(file); 76 | expect(input.files.item(0)).toStrictEqual(file); 77 | expect(input.files).toHaveLength(1); 78 | }); 79 | }); 80 | describe("Should be able to render the Discusssion Page", () => { 81 | test("Should be able to reset the comment", () => { 82 | const { getByTestId } = render(); 83 | const commentButton = getByTestId("reset-comment"); 84 | const name = screen.getByPlaceholderText("Your name"); 85 | const comment = screen.getByTestId("comment-section-test"); 86 | userEvent.click(commentButton); 87 | expect(name.value).toMatch(""); 88 | expect(comment).toHaveTextContent(""); 89 | }); 90 | test("Image should be previewed after entering url", async () => { 91 | render(); 92 | const commentSection = screen.getByTestId("comment-section-test"); 93 | commentSection.textContent = 94 | "https://letsenhance.io/static/b8eda2f8914d307d52f725199fb0c5e6/62e7b/MainBefore.jpg"; 95 | const imagePreview = await screen.findByTestId("image-preview"); 96 | expect(imagePreview).toBeVisible(); 97 | }); 98 | }); 99 | -------------------------------------------------------------------------------- /src/components/Discussion/commentCard.jsx: -------------------------------------------------------------------------------- 1 | import { useState } from "react"; 2 | import { AiFillDelete } from "react-icons/ai"; 3 | import parse from "html-react-parser"; 4 | import Reply from "./reply"; 5 | 6 | var imageUrlRegex = /\b(https?:\/\/[^\s]+)/g; 7 | 8 | const CommentCard = ({ value, deleteComment }) => { 9 | const { _id, name, rating, content } = value; 10 | const [isOpen, setIsOpen] = useState(false); 11 | const [reply, setReply] = useState([]); 12 | const [toggle, setToggle] = useState(true); 13 | const [replyBox, setReplyBox] = useState(false); 14 | 15 | function addReply(name, comment) { 16 | setReply((prevReply) => [...prevReply, { name, comment }]); 17 | setIsOpen(!isOpen); 18 | } 19 | const deleteReply = (index) => { 20 | let deleteList = [...reply]; 21 | deleteList.splice(index, 1); 22 | setReply(deleteList); 23 | }; 24 | 25 | const imageUrl = value?.content?.match(imageUrlRegex); 26 | return ( 27 | <> 28 |
29 |
30 |
31 |
32 |
33 | {name} 34 |
35 |
36 | {rating}⭐️ 37 |
38 |
39 |
setToggle(!toggle)} 43 | > 44 | {toggle ? "-" : "+"} 45 |
46 |
47 | {toggle && ( 48 |
49 |
50 | {parse(content?.replace(imageUrlRegex, ""))} 51 |
52 | {imageUrl && ( 53 | 59 | )} 60 | 61 |
62 | 69 | 77 | 84 |
85 |
86 | )} 87 |
88 |
89 | {isOpen && } 90 | {reply?.map(({ id, name, comment }) => { 91 | return ( 92 | <> 93 | {replyBox && ( 94 |
95 |
96 |
97 |
98 |
{name}
99 |
100 |
101 |
{parse(`${comment}`)}
102 |
103 | 106 |
107 |
108 |
109 |
110 |
111 | )} 112 | 113 | ); 114 | })} 115 | 116 | ); 117 | }; 118 | 119 | export default CommentCard; 120 | -------------------------------------------------------------------------------- /src/components/Jobs/index.jsx: -------------------------------------------------------------------------------- 1 | import React, { useState } from "react"; 2 | import Navbar from "../Navbar"; 3 | import { Link } from "react-router-dom"; 4 | import "./index.css"; 5 | import Job from "./../../Assets/jobs.json"; 6 | import Filter from "../Filter"; 7 | import { AiOutlineHeart, AiFillHeart } from "react-icons/ai"; 8 | 9 | const experience = [ 10 | { min: 0, max: 1 }, 11 | { min: 2, max: 3 }, 12 | { min: 4, max: 5 }, 13 | { min: 5, max: 10 }, 14 | ]; 15 | 16 | const Jobs = () => { 17 | const JobData = JSON.parse(localStorage.getItem("item")) || []; 18 | const [filteredJobs, setFilteredJobs] = useState([...JobData, ...Job]); 19 | const [searchterm, setSearchTerm] = useState(""); 20 | const [active, setActive] = useState(false); 21 | function handleJobFilter(event) { 22 | const value = event.target.innerText; 23 | event.preventDefault(); 24 | setFilteredJobs( 25 | Job.filter((job) => { 26 | return job.role === value; 27 | }) 28 | ); 29 | } 30 | function saveClick(id, logo, company, position, location, posted) { 31 | window.localStorage.setItem( 32 | "Job", 33 | JSON.stringify(id, logo, company, position, location, posted) 34 | ); 35 | console.log(JobData); 36 | } 37 | const searchEvent = (event) => { 38 | const data = event.target.value; 39 | setSearchTerm(data); 40 | if (searchterm !== "" || searchterm.length > 2) { 41 | const filterData = Job.filter((item) => { 42 | if (item) { 43 | return Object.values(item) 44 | .join("") 45 | .toLowerCase() 46 | .includes(searchterm.toLowerCase()); 47 | } else { 48 | return 0; 49 | } 50 | }); 51 | setFilteredJobs(filterData); 52 | } else { 53 | setFilteredJobs(Job); 54 | } 55 | }; 56 | function handleExperienceFilter(checkedState) { 57 | let filters = []; 58 | checkedState.forEach((item, index) => { 59 | if (item === true) { 60 | const filterS = Job.filter((job) => { 61 | return ( 62 | job.experience >= experience[index].min && 63 | job.experience <= experience[index].max 64 | ); 65 | }); 66 | filters = [...filters, ...filterS]; 67 | } 68 | setFilteredJobs(filters); 69 | }); 70 | } 71 | return ( 72 | <> 73 | 74 |
75 |
76 |
77 |

Our Jobs

78 |
79 |
80 |
81 |
82 | {filteredJobs.map( 83 | ({ id, logo, company, position, location, posted, role }) => { 84 | return ( 85 |
86 |
87 |
88 | 20 91 | ? logo 92 | : require(`../../Assets/images/${logo}`) 93 | } 94 | alt="logo" 95 | className="job-profile" 96 | /> 97 |
98 |

{company}

99 |

{position}

100 |
101 |

{location}

102 |

{role}

103 |
104 |
105 |
106 |
107 |
108 | Apply Now 109 |
110 |
111 | { 114 | saveClick( 115 | { 116 | id, 117 | logo, 118 | company, 119 | position, 120 | location, 121 | posted, 122 | }, 123 | setActive(!active) 124 | ); 125 | }} 126 | > 127 | {JSON.parse(localStorage.getItem("Job"))?.id === 128 | id ? ( 129 | 130 | ) : ( 131 | 132 | )} 133 | 134 |
135 |
136 |
137 |
138 | ); 139 | } 140 | )} 141 |
142 | 143 | 149 |
150 |
151 | 152 | ); 153 | }; 154 | 155 | export default Jobs; 156 | -------------------------------------------------------------------------------- /src/Assets/jobs.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": 1, 4 | "company": "Amazon", 5 | "logo": "amazon.png", 6 | "position": "Fullstack Developer", 7 | "role": "Fullstack", 8 | "level": "Full Stack", 9 | "experience": 1, 10 | "salary":10000, 11 | "location": "Remote", 12 | "posted": "2022-10-15" 13 | }, 14 | { 15 | "id": 2, 16 | "company": "FLP", 17 | "logo": "flp.jpeg", 18 | "position": "Digital Marketing", 19 | "role": "Digital Marketing", 20 | "level": "Negative", 21 | "experience": 0, 22 | "salary": 20000, 23 | "location": "Remote", 24 | "posted": "2022-11-15" 25 | }, 26 | { 27 | "id": 3, 28 | "company": "Paytm", 29 | "logo": "paytm.png", 30 | "position": "Jr. Frontend Developer", 31 | "role": "Frontend", 32 | "level": "Junior", 33 | "experience": 2, 34 | "salary": 30000, 35 | "location": "Mumbai", 36 | "posted": "2022-09-15" 37 | }, 38 | { 39 | "id": 4, 40 | "company": "Tesla", 41 | "logo": "tesla.png", 42 | "position": "Software Engineer", 43 | "role": "Full Stack", 44 | "level": "Midweight", 45 | "experience": 3, 46 | "salary": 40000, 47 | "location": "Gurugram", 48 | "posted": "2022-07-15" 49 | }, 50 | { 51 | "id": 5, 52 | "company": "Elastic Run", 53 | "logo": "elastic-run.jpeg", 54 | "position": "Jr. Backend Developer", 55 | "role": "Backend", 56 | "level": "Junior", 57 | "experience": 1, 58 | "salary": 50000, 59 | "location": "Jaipur", 60 | "posted": "2022-04-15" 61 | }, 62 | { 63 | "id": 6, 64 | "company": "TCS", 65 | "logo": "tcs.webp", 66 | "position": "Jr. Devops Engineer", 67 | "role": "Devops", 68 | "level": "Negative", 69 | "experience": 2, 70 | "salary": 15000, 71 | "location": "Bangalore", 72 | "posted": "2022-08-15" 73 | }, 74 | { 75 | "id": 7, 76 | "company": "Myntra", 77 | "logo": "myntra.png", 78 | "position": "Jr. Frontend Developer", 79 | "role": "Frontend", 80 | "level": "Junior", 81 | "experience": 3, 82 | "salary": 20000, 83 | "location": "Remote", 84 | "posted": "2022-09-15" 85 | }, 86 | { 87 | "id": 8, 88 | "company": "Synopsys", 89 | "logo": "synopsys.png", 90 | "position": "Full Stack Engineer", 91 | "role": "Fullstack", 92 | "level": "Negative", 93 | "experience": 1, 94 | "salary": 70000, 95 | "location": "Hyderabad", 96 | "posted": "2022-11-15" 97 | }, 98 | { 99 | "id": 9, 100 | "company": "Optum", 101 | "logo": "optum.png", 102 | "position": "Front-End Developer", 103 | "role": "Frontend", 104 | "level": "Junior", 105 | "experience": 0, 106 | "salary": 90000, 107 | "location": "New Delhi", 108 | "posted": "2022-10-15" 109 | }, 110 | { 111 | "id": 10, 112 | "company": "Infosys", 113 | "logo": "infosys.png", 114 | "position": "React Developer", 115 | "role": "Frontend", 116 | "level": "Senior", 117 | "experience": 2, 118 | "salary": 10000, 119 | "location": "Bangalore", 120 | "posted": "2022-12-15" 121 | }, 122 | { 123 | "id": 11, 124 | "company": "Tech Mahindra", 125 | "logo": "tech-mahindra.png", 126 | "position": "NodeJS Developer", 127 | "role": "Backend", 128 | "level": "Junior", 129 | "experience": 1, 130 | "salary": 18000, 131 | "location": "Jaipur", 132 | "posted": "2022-08-15" 133 | }, 134 | { 135 | "id": 12, 136 | "company": "Cloud Mentor", 137 | "logo": "cloud-mentor.jpeg", 138 | "position": "Software Engineer", 139 | "role": "Full Stack", 140 | "level": "Negative", 141 | "experience": 3, 142 | "salary": 25000, 143 | "location": "Surat", 144 | "posted": "2022-01-15" 145 | }, 146 | { 147 | "id": 13, 148 | "company": "Flipkart", 149 | "logo": "flipkart.jpeg", 150 | "position": "Sr. Devops Engineer", 151 | "role": "Devops", 152 | "level": "Negative", 153 | "experience": 2, 154 | "salary": 70000, 155 | "location": "Mumbai", 156 | "posted": "2021-05-15" 157 | }, 158 | { 159 | "id": 14, 160 | "company": "Cognizant", 161 | "logo": "cognizant.webp", 162 | "position": "Front-End Developer", 163 | "role": "Frontend", 164 | "level": "Negative", 165 | "experience": 2, 166 | "salary": 90000, 167 | "location": "Hyderabad", 168 | "posted": "2021-07-15" 169 | }, 170 | { 171 | "id": 15, 172 | "company": "IBM", 173 | "logo": "ibm.jpeg", 174 | "position": "Jr. Backend Developer", 175 | "role": "Backend", 176 | "level": "Negative", 177 | "experience": 1, 178 | "salary": 40000, 179 | "location": "Bangalore", 180 | "posted": "2021-09-10" 181 | }, 182 | { 183 | "id": 16, 184 | "company": "Accenture", 185 | "logo": "accenture.jpeg", 186 | "position": "Sr. Devops Engineer", 187 | "role": "Devops", 188 | "level": "Negative", 189 | "experience": 3, 190 | "salary": "20000", 191 | "location": "New Delhi", 192 | "posted": "2021-10-15" 193 | }, 194 | { 195 | "id": 17, 196 | "company": "Oracle", 197 | "logo": "oracle.png", 198 | "position": "Digital Marketing", 199 | "role": "Digital Marketing", 200 | "level": "Negative", 201 | "experience": 4, 202 | "salary": 15000, 203 | "location": "Noida", 204 | "posted": "2021-11-15" 205 | }, 206 | { 207 | "id": 18, 208 | "company": "Delloite", 209 | "logo": "deloitte.png", 210 | "position": "Full Stack Engineer", 211 | "role": "Full Stack", 212 | "level": "Negative", 213 | "experience": 7, 214 | "salary": 80000, 215 | "location": "Mumbai", 216 | "posted": "2021-07-15" 217 | }, 218 | { 219 | "id": 19, 220 | "company": "SAP Labs", 221 | "logo": "sap.jpeg", 222 | "position": "Sr. Devops Engineer", 223 | "role": "Devops", 224 | "level": "Negative", 225 | "experience": 4, 226 | "salary": 67000, 227 | "location": "Gurugram", 228 | "posted": "2021-11-15" 229 | }, 230 | { 231 | "id": 20, 232 | "company": "Facebook", 233 | "logo": "facebook.png", 234 | "position": "Full Stack Engineer", 235 | "role": "Full Stack", 236 | "level": "Negative", 237 | "experience": 1, 238 | "salary": 56000, 239 | "location": "Mumbai", 240 | "posted": "2021-12-15" 241 | } 242 | ] 243 | 244 | 245 | -------------------------------------------------------------------------------- /src/components/Discussion/index.jsx: -------------------------------------------------------------------------------- 1 | import { useState, useRef, useEffect } from "react"; 2 | import "./index.css"; 3 | import Navbar from "../Navbar"; 4 | import StarRating from "./rating"; 5 | import CommentCard from "./commentCard"; 6 | import Editor from "./editor"; 7 | import { BiUserCircle } from "react-icons/bi"; 8 | import sanityClient from "../../client"; 9 | import axios from "axios"; 10 | 11 | var imageUrlRegex = /\b(https?:\/\/[^\s]+)/g; 12 | 13 | const config = { 14 | url: `${process.env.REACT_APP_BASE_URL}`, 15 | method: "post", 16 | headers: { 17 | "Content-type": "application/json", 18 | Authorization: `Bearer ${process.env.REACT_APP_BEARER_TOKEN}`, 19 | }, 20 | }; 21 | 22 | export default function Discussion() { 23 | const [name, setName] = useState(""); 24 | const [rating, setRating] = useState(0); 25 | const [imageUrl, setImageUrl] = useState(""); 26 | const commentRef = useRef(); 27 | const [commentList, setCommentList] = useState(null); 28 | const [urlList, setUrlList] = useState([]); 29 | 30 | const handleSubmit = (e) => { 31 | e.preventDefault(); 32 | if (name === "" || commentRef.length === "") { 33 | window.alert("Enter the credentials"); 34 | } else { 35 | axios({ 36 | ...config, 37 | data: { 38 | mutations: [ 39 | { 40 | create: { 41 | name, 42 | content: commentRef.current.innerText, 43 | rating, 44 | _type: "Comment", 45 | }, 46 | }, 47 | ], 48 | }, 49 | }) 50 | .then((result) => console.log(result)) 51 | .catch((error) => console.error(error)); 52 | 53 | const newComment = commentList.unshift({ 54 | name, 55 | content: commentRef.current.innerText, 56 | rating, 57 | _type: "Comment", 58 | }); 59 | setName(""); 60 | setImageUrl(""); 61 | commentRef.current.innerText = ""; 62 | setCommentList(...newComment, ...commentList); 63 | } 64 | }; 65 | 66 | const handleNameChange = (e) => { 67 | setName(e.target.value); 68 | }; 69 | const handleCommentChange = (e) => { 70 | const value = e.currentTarget.innerText; 71 | const newLength = value?.length; 72 | if (newLength === 0) { 73 | setUrlList([]); 74 | setImageUrl(); 75 | return; 76 | } 77 | if (value?.match(imageUrlRegex)) { 78 | setUrlList(value?.match(imageUrlRegex)); 79 | } else { 80 | setUrlList([]); 81 | } 82 | }; 83 | 84 | useEffect(() => { 85 | if (urlList?.length !== 0) { 86 | setImageUrl(urlList[0]); 87 | } else { 88 | setImageUrl(""); 89 | } 90 | }, [urlList]); 91 | 92 | const deleteComment = (id) => { 93 | axios({ 94 | ...config, 95 | data: { 96 | mutations: [ 97 | { 98 | delete: { 99 | id: id, 100 | }, 101 | }, 102 | ], 103 | }, 104 | }) 105 | .then((result) => console.log(result)) 106 | .catch((error) => console.error(error)); 107 | let removeData = [...commentList]; 108 | removeData.splice(id, 1); 109 | setCommentList(removeData); 110 | }; 111 | useEffect(() => { 112 | sanityClient 113 | .fetch( 114 | `*[_type == "Comment"]{ 115 | _id, 116 | name, 117 | content, 118 | rating, 119 | hexCode, 120 | } | order(_createdAt desc)` 121 | ) 122 | .then((commentList) => { 123 | setCommentList(commentList); 124 | }) 125 | .catch(console.error); 126 | }, []); 127 | return ( 128 | <> 129 | 130 |
131 |
132 |
JOB DISQUS
133 | 134 |
135 |
136 |
137 |
{commentList?.length} Comments
138 |
139 |
140 | 141 |
142 | 149 |
150 |
151 |
152 |
153 |
You rated this
154 | 155 |
156 |
157 |
166 |
167 | 168 | 169 | 176 |
177 |
178 | {imageUrl && ( 179 | 184 | )} 185 |
186 |
187 | 188 |
189 |
190 |
191 |
192 | {commentList && 193 | commentList?.map((comments) => { 194 | return ( 195 | deleteComment(comments._id)} 199 | /> 200 | ); 201 | })} 202 |
203 |
204 | 205 | ); 206 | } 207 | -------------------------------------------------------------------------------- /src/components/PostJob/index.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { useState } from "react"; 3 | import Navbar from "../Navbar"; 4 | import "./index.css"; 5 | import { useNavigate } from "react-router-dom"; 6 | 7 | const PostJob = () => { 8 | const [company, setCompany] = useState(""); 9 | const [logo, setLogo] = useState(""); 10 | const [position, setPosition] = useState(""); 11 | const [salary, setSalary] = useState(""); 12 | const [experience, setExperience] = useState(""); 13 | const [role, setRole] = useState(""); 14 | const [location, setLocation] = useState(""); 15 | 16 | const navigate=useNavigate(); 17 | const getBase64 = (file) => { 18 | return new Promise((resolve, reject) => { 19 | const reader = new FileReader(); 20 | reader.onload = () => resolve(reader.result); 21 | reader.onabort = (error) => reject(error); 22 | reader.readAsDataURL(file); 23 | }); 24 | }; 25 | const handleImg = (e) => { 26 | const file = e.target.files[0]; 27 | getBase64(file).then((base64) => { 28 | localStorage["logo"] = base64; 29 | setLogo(base64); 30 | }); 31 | }; 32 | 33 | const handleSubmitButton = (e) => { 34 | const jobPost = { 35 | company, 36 | position, 37 | salary, 38 | experience, 39 | role, 40 | location, 41 | logo 42 | }; 43 | e.preventDefault(); 44 | if (company === "") { 45 | window.alert("Enter name"); 46 | } else if (position === "") { 47 | window.alert("Enter position"); 48 | } else if (experience === "") { 49 | window.alert("Enter Experience"); 50 | } else if (salary === "") window.alert("Enter Salary"); 51 | else { 52 | let savedItem = []; 53 | if (localStorage.getItem("item")) { 54 | savedItem = JSON.parse(localStorage.getItem("item")); 55 | } 56 | localStorage.setItem("item", JSON.stringify([...savedItem, {jobPost}])); 57 | window.alert("Form Submitted Successfully"); 58 | navigate("/Jobs"); 59 | } 60 | }; 61 | return ( 62 |
63 | 64 | 65 |
66 |
67 |

Post a Job

68 |
69 |
70 |
71 |
72 |

Fill the form

73 |
74 |
75 |
76 | 79 | setCompany(e.target.value)} 85 | required 86 | /> 87 |
88 |
89 | 92 | setLocation(e.target.value)} 98 | required 99 | /> 100 |
101 |
102 | 105 | 114 |
115 |
116 | 117 | 133 |
134 |
135 | 138 | setRole(e.target.value)} 144 | required 145 | /> 146 |
147 | 148 |
setExperience(e.target.value)} 151 | > 152 | 153 | 162 | 171 | 180 | 189 |
190 | 191 |
192 | 193 | 207 |
208 |
209 | 212 |
213 |
214 |
215 |
216 | ); 217 | }; 218 | 219 | export default PostJob; 220 | -------------------------------------------------------------------------------- /src/components/Discussion/index.css: -------------------------------------------------------------------------------- 1 | .discussion { 2 | display: flex; 3 | gap: 50px; 4 | justify-content: center; 5 | margin-top: 20px; 6 | } 7 | .discuss { 8 | text-align: center; 9 | margin-top: 10px; 10 | margin-bottom: 10px; 11 | font-size: 27px; 12 | font-weight: bold; 13 | color: blue; 14 | } 15 | .right { 16 | display: flex; 17 | flex-direction: column; 18 | justify-content: center; 19 | } 20 | 21 | .discussion .comment-form { 22 | display: flex; 23 | flex-direction: column; 24 | gap: 10px; 25 | width: 450px; 26 | background: #fff; 27 | } 28 | .comment-name { 29 | display: flex; 30 | gap: 116px; 31 | margin-bottom: 35px; 32 | align-items: center; 33 | } 34 | .reply-icon-name { 35 | display: flex; 36 | gap: 9px; 37 | margin-left: -10%; 38 | } 39 | .comments-name { 40 | margin-bottom: 15px; 41 | } 42 | .rating-text { 43 | display: inline-block; 44 | color: #546673; 45 | margin-right: 4px; 46 | font-weight: 500; 47 | font-size: 14px; 48 | margin-left: 5%; 49 | } 50 | .star-rating { 51 | display: flex; 52 | gap: 2px; 53 | } 54 | .icon-name { 55 | display: flex; 56 | gap: 9px; 57 | } 58 | .user-icon { 59 | font-size: 30px; 60 | } 61 | .discussion .submit:hover { 62 | background: black; 63 | transition: 1s ease; 64 | cursor: pointer; 65 | } 66 | .icon-button { 67 | display: flex; 68 | align-items: center; 69 | gap: 90px; 70 | border: 2px solid #dbdfe4; 71 | border-top: 0px solid #dbdfe4; 72 | background: #f6f8f9; 73 | height: 34px; 74 | border-bottom-right-radius: 15px; 75 | border-bottom-left-radius: 15px; 76 | margin-bottom: 20px; 77 | } 78 | .image-preview { 79 | height: 100px; 80 | margin-left: 5%; 81 | margin-top: 10%; 82 | } 83 | .discussion .form-control { 84 | height: 35px; 85 | padding: 19px; 86 | } 87 | .discussion .comment { 88 | overflow: auto; 89 | overflow-wrap: break-word; 90 | min-height: 150px; 91 | height: auto; 92 | max-height: 300px; 93 | border: 2px solid #dbdfe4; 94 | padding: 19px; 95 | border-top-left-radius: 20px; 96 | border-top-right-radius: 20px; 97 | word-break: break-all; 98 | } 99 | .discussion .comment:empty::before, 100 | .commenting-form .comment:empty::before { 101 | content: attr(data-placeholder); 102 | font-size: 13px; 103 | } 104 | .image-loader { 105 | margin-top: 60%; 106 | margin-left: -50%; 107 | } 108 | .image-gif { 109 | height: 40px; 110 | width: 40px; 111 | } 112 | .discussion .comment-box { 113 | width: 300px; 114 | background: #f9f9f9; 115 | border-radius: 10px; 116 | } 117 | .comment-box .name, 118 | .comment-box .comment { 119 | color: #000; 120 | padding: 5px; 121 | margin-top: 12px; 122 | } 123 | .comment-box .name { 124 | font-size: 17px; 125 | padding: 4px; 126 | text-align: end; 127 | color: blue; 128 | font-weight: bold; 129 | overflow: auto; 130 | overflow-wrap: break-word; 131 | } 132 | .comment-box .comment { 133 | overflow: auto; 134 | overflow-wrap: break-word; 135 | min-height: 40px; 136 | height: auto; 137 | max-height: 300px; 138 | width: 100%; 139 | white-space: pre-wrap; 140 | } 141 | .comment-box .comments { 142 | margin-top: 3px; 143 | overflow: auto; 144 | overflow-wrap: break-word; 145 | min-height: 90px; 146 | height: auto; 147 | max-height: 300px; 148 | width: 100%; 149 | border-top-right-radius: 15px; 150 | border-top-left-radius: 15px; 151 | } 152 | 153 | .reply { 154 | width: 40px; 155 | background: #fff; 156 | cursor: pointer; 157 | cursor: pointer; 158 | color: slategrey; 159 | opacity: 0.9; 160 | } 161 | .reply:hover { 162 | color: black; 163 | opacity: 1; 164 | } 165 | .delete { 166 | width: 40px; 167 | padding: 5px; 168 | background: #f6f8f9; 169 | cursor: pointer; 170 | float: right; 171 | color: red; 172 | font-size: 17px; 173 | } 174 | .reply-btn { 175 | font-size: 10px; 176 | background: #f6f8f9; 177 | } 178 | .job-role { 179 | display: flex; 180 | font-size: 20px; 181 | font-weight: normal; 182 | justify-content: center; 183 | gap: 45px; 184 | margin-top: 20px; 185 | } 186 | .job-role > h3 { 187 | font-size: 18px; 188 | margin-top: 6px; 189 | } 190 | .job-role > h2 { 191 | font-size: 25px; 192 | } 193 | .discussion .comment-section { 194 | margin: 30px; 195 | display: flex; 196 | flex-direction: column; 197 | } 198 | .rate-button { 199 | background-color: transparent; 200 | border: none; 201 | outline: none; 202 | cursor: pointer; 203 | } 204 | .on { 205 | color: gold; 206 | } 207 | .off { 208 | color: grey; 209 | } 210 | .line { 211 | font-weight: 700; 212 | font-size: 18px; 213 | color: #343434; 214 | font-family: Georgia, times, serif; 215 | } 216 | .rating { 217 | margin-top: 10px; 218 | } 219 | .review { 220 | padding: 10px; 221 | width: 33%; 222 | cursor: text; 223 | margin-bottom: 20px; 224 | background: #f6f8f9; 225 | border-radius: 13px; 226 | margin-top: 40px; 227 | } 228 | .comment-boxes { 229 | display: flex; 230 | justify-content: center; 231 | width: 100%; 232 | } 233 | .comments-boxes { 234 | display: flex; 235 | justify-content: center; 236 | width: 70%; 237 | margin-left: 120px; 238 | margin-top: 0px; 239 | } 240 | .commenting-form { 241 | width: 60%; 242 | justify-content: center; 243 | flex-direction: column; 244 | margin-top: 10px; 245 | margin-left: auto; 246 | margin-right: auto; 247 | } 248 | 249 | .styling-buttons { 250 | display: flex; 251 | gap: 12px; 252 | justify-content: flex-start; 253 | } 254 | .submit { 255 | background: blue; 256 | color: #fff; 257 | padding: 2px 9px 2px 9px; 258 | border-radius: 10px; 259 | margin-left: 15%; 260 | height: 28px; 261 | } 262 | .replied-comments { 263 | background: blue; 264 | color: #fff; 265 | padding: 2px 9px 2px 9px; 266 | border-radius: 10px; 267 | margin-left: -28%; 268 | height: 28px; 269 | } 270 | .bold, 271 | .italic, 272 | .underline, 273 | .code, 274 | .comment-image { 275 | cursor: pointer; 276 | width: 30px; 277 | background: transparent; 278 | } 279 | .comment-left { 280 | display: flex; 281 | gap: 20px; 282 | align-items: center; 283 | } 284 | only-image .img { 285 | height: 100px; 286 | } 287 | .reply-section { 288 | width: 70%; 289 | margin-left: 20%; 290 | cursor: pointer; 291 | } 292 | .buttons .view-reply { 293 | color: grey; 294 | font-size: 10px; 295 | cursor: pointer; 296 | background-color: #f6f8f9; 297 | opacity: 0.9; 298 | } 299 | .buttons .view-reply:hover { 300 | opacity: 1; 301 | color: black; 302 | } 303 | .reply-count { 304 | margin-left: 10%; 305 | } 306 | .top-area { 307 | display: flex; 308 | justify-content: space-between; 309 | margin: 3px; 310 | } 311 | .add-icon { 312 | cursor: pointer; 313 | font-size: 37px; 314 | height: 38px; 315 | } 316 | .edit-button { 317 | margin-left: 15%; 318 | cursor: pointer; 319 | } 320 | .comments-form { 321 | width: 27.5%; 322 | margin-left: 36%; 323 | background: none; 324 | } 325 | 326 | @media (max-width: 640px) { 327 | .discussion .comment-form { 328 | width: 270px; 329 | } 330 | .comment-name { 331 | gap: 20px; 332 | } 333 | .styling-buttons { 334 | gap: 5px; 335 | } 336 | .icon-button { 337 | gap: 0px; 338 | } 339 | .input-group { 340 | width: 123%; 341 | } 342 | .buttons .view-reply { 343 | font-size: 12px; 344 | } 345 | .bold, 346 | .italic, 347 | .underline, 348 | .code, 349 | .comment-image { 350 | font-size: 10px; 351 | } 352 | } 353 | .image-text-editor { 354 | height: 100px; 355 | width: 100px; 356 | } 357 | .text-editor { 358 | font-size: 10px; 359 | font-weight: 100; 360 | overflow: auto; 361 | overflow-wrap: break-word; 362 | } 363 | --------------------------------------------------------------------------------