diff --git a/.env.development b/.env.development
deleted file mode 100644
index 2592df8b54..0000000000
--- a/.env.development
+++ /dev/null
@@ -1,5 +0,0 @@
-# Development environment settings
-REACT_APP_APIENDPOINT="http://localhost:4500/api"
-SKIP_PREFLIGHT_CHECK=true
-DISABLE_ESLINT_PLUGIN=true
-REACT_APP_DEF_PWD=123Welcome!
\ No newline at end of file
diff --git a/src/actions/collaborationAdsActions.js b/src/actions/collaborationAdsActions.js
new file mode 100644
index 0000000000..6500892552
--- /dev/null
+++ b/src/actions/collaborationAdsActions.js
@@ -0,0 +1,35 @@
+import axios from 'axios';
+import { ENDPOINTS } from '../utils/URL';
+import {toast} from 'react-toastify';
+
+export const CREATE_COLLABORATION_ADS_REQUEST = 'CREATE_COLLABORATION_ADS_REQUEST';
+export const CREATE_COLLABORATION_ADS_SUCCESS = 'CREATE_COLLABORATION_ADS_SUCCESS';
+export const CREATE_COLLABORATION_ADS_FAIL = 'CREATE_COLLABORATION_ADS_FAIL';
+
+// eslint-disable-next-line import/prefer-default-export
+export const createCollaborationAds = (formData) => async (dispatch) => {
+
+ try {
+ dispatch({ type: CREATE_COLLABORATION_ADS_REQUEST });
+ const response = await axios.post(`${ENDPOINTS.JOBS}`, formData);
+
+ dispatch({
+ type: 'CREATE_COLLABORATION_ADS_SUCCESS',
+ payload: response.data, // You can also use formData directly
+ });
+
+ if (response.status === 200 || response.status === 201)
+ toast.success('Collaboration Ads created successfully!');
+ }
+ catch(error) {
+ toast.error('Error updating the details. Please try again.');
+ dispatch({ type: 'CREATE_COLLABORATION_ADS_FAIL' });
+
+
+ if (error.response?.status === 500) {
+ toast.error('Error updating the details. Please try again.');
+ }
+ else { toast.error('Error updating the details. Please try again.'); }
+ }
+};
+
diff --git a/src/components/Collaboration/JobAdsCreation.jsx b/src/components/Collaboration/JobAdsCreation.jsx
new file mode 100644
index 0000000000..6677526b74
--- /dev/null
+++ b/src/components/Collaboration/JobAdsCreation.jsx
@@ -0,0 +1,571 @@
+import { useEffect, useState, useRef } from 'react';
+import { useSelector, useDispatch } from 'react-redux';
+import styles from './JobAdsCreation.module.css';
+import { toast } from 'react-toastify';
+import { Editor } from '@tinymce/tinymce-react';
+import { ENDPOINTS } from '../../utils/URL';
+import OneCommunityImage from '../../assets/images/logo2.png';
+import { isValidDropboxImageUrl, isValidUrl } from '../../utils/checkValidURL';
+import { createCollaborationAds } from '../../actions/collaborationAdsActions';
+import getWordCount from '../../utils/getWordCount';
+import hasPermission from '../../utils/permissions';
+
+function JobAdsCreation() {
+ const dispatch = useDispatch();
+ // const canCreateCollabJobAds = hasPermission('createCollabJobAds');
+ // console.log('canCreateCollabJobAds');
+ // console.log(canCreateCollabJobAds);
+
+ const [canCreateCollabJobAds, setCanCreateCollabJobAds] = useState(null);
+
+ useEffect(() => {
+ const checkPermission = async () => {
+ try {
+ const result = await dispatch(hasPermission('createCollabJobAds'));
+ console.log('createCollabJobAds permission:', result);
+ setCanCreateCollabJobAds(Boolean(result));
+ } catch (error) {
+ console.error('Error checking permission', error);
+ setCanCreateCollabJobAds(false);
+ }
+ };
+
+ checkPermission();
+ }, [dispatch]);
+
+ // const canCreateCollabJobAdsDis = await dispatch(hasPermission('createCollabJobAds'));
+ const [loading, setLoading] = useState('');
+ // const formFields = ['imageUrl', 'location', 'applyLink', 'jobDetailsLink'];
+ const textareaFields = [
+ { key: 'description', display: 'Description' },
+ { key: 'requirements', display: 'Requirements' },
+ // { key: 'skills', display: 'Skills' },
+ { key: 'projects', display: 'Projects' },
+ // { key: 'whoareyou', display: 'Who are you' },
+ // apply: '',
+ { key: 'ourCommunity', display: 'Our Community' },
+ // { key: 'whoweare', display: 'Who are we' },
+ ];
+
+ const formFields = [
+ { key: 'imageUrl', display: 'Image Url' },
+ { key: 'location', display: 'Location' },
+ // { key: 'applyLink', display: 'Apply Link' },
+ // { key: 'jobDetailsLink', display: 'Job Details Link' },
+ ];
+
+ const initialState = {
+ title: '',
+ category: '',
+ /* new fields */
+ // about: '',
+ requirements: '',
+ // skills: '',
+ projects: '',
+ // whoareyou: '',
+ // apply: '',
+ // whoweare: '',
+ ourCommunity: '',
+ /* newly */
+ description: '',
+ imageUrl: '',
+ location: 'remote',
+ applyLink: '',
+ jobDetailsLink: '',
+ };
+ const [formData, setFormData] = useState({ ...initialState });
+ const [categories, setCategories] = useState([]);
+ const [positions, setPositions] = useState([]);
+ const [jobFormsAll, setJobFormsAll] = useState([]);
+ const [jobTemplates, setJobTemplates] = useState([]);
+
+ const [errors, setErrors] = useState({});
+ const darkMode = useSelector(state => state.theme.darkMode);
+ // const dispatch = useDispatch();
+ const textareaRef = useRef(null);
+
+ const TINY_MCE_INIT_OPTIONS = {
+ license_key: 'gpl',
+ menubar: false,
+ // placeholder: 'Description (10-word minimum) and reference link',
+ // advlist
+ plugins: 'autolink autoresize lists link help wordcount preview ',
+ toolbar:
+ // eslint-disable-next-line no-multi-str
+ 'bold italic underline link removeformat | bullist numlist outdent indent |\
+ styleselect fontsizeselect | forecolor backcolor |\
+ help | preview ',
+ branding: false,
+ toolbar_mode: 'sliding',
+ min_height: 180,
+ max_height: 600,
+ width: 700,
+ autoresize_bottom_margin: 1,
+ content_style: 'body { cursor: text !important; }',
+ // images_upload_handler: customImageUploadHandler,
+ skin: darkMode ? 'oxide-dark' : 'oxide',
+ content_css: darkMode ? 'dark' : 'default',
+ };
+
+ const TINY_MCE_INIT_OPTIONS_MEDIA = {
+ license_key: 'gpl',
+ menubar: false,
+ // placeholder: 'Description (10-word minimum) and reference link',
+ // advlist
+ plugins: 'autolink autoresize lists link help wordcount preview media',
+ toolbar:
+ // eslint-disable-next-line no-multi-str
+ 'bold italic underline link removeformat | bullist numlist outdent indent |\
+ styleselect fontsizeselect | forecolor backcolor |\
+ help | preview | media',
+ branding: false,
+ toolbar_mode: 'sliding',
+ min_height: 180,
+ max_height: 600,
+ autoresize_bottom_margin: 1,
+ content_style: 'body { cursor: text !important; }',
+ // images_upload_handler: customImageUploadHandler,
+ skin: darkMode ? 'oxide-dark' : 'oxide',
+ content_css: darkMode ? 'dark' : 'default',
+ };
+
+ const submitJobAds = async () => {
+ setLoading(true);
+ try {
+ /*
+ const response = await axios.post(`${ENDPOINTS.JOBS}`, formData);
+ console.log('response inside submitJobAds:');
+ console.log(response);
+ if (!response.status === 201) {
+ throw new Error(`Failed to submit jobs: ${response.statusText}`);
+ }
+
+ const data = await response.data;
+ console.log('data inside submitJobAds:');
+ console.log(data);
+
+ toast.success('Collaboration Ads created successfully');
+ */
+ dispatch(createCollaborationAds(formData));
+
+ // const res = await createCollaborationAds(formData);
+ // console.log(res);
+ setLoading(false);
+ setFormData({ ...initialState });
+ } catch (error) {
+ toast.error('Failed to submit jobs');
+ }
+ };
+
+ const fetchCategories = async () => {
+ try {
+ const response = await fetch(`${ENDPOINTS.JOB_CATEGORIES}`, { method: 'GET' });
+ if (!response.ok) throw new Error(`Failed to fetch categories: ${response.statusText}`);
+
+ const data = await response.json();
+ const sortedCategories = data.categories.sort((a, b) => a.localeCompare(b));
+ setCategories(sortedCategories);
+ } catch (error) {
+ toast.error('Error fetching categories');
+ }
+ };
+
+ // Get all templates
+ const fetchTemplates = async () => {
+ try {
+ const res = await fetch(`${ENDPOINTS.GET_ALL_TEMPLATES}`, {
+ method: 'GET',
+ headers: {
+ Authorization: localStorage.getItem('token'),
+ },
+ });
+
+ if (!res.ok) throw new Error(`Failed to fetch all Templates: ${response.statusText}`);
+
+ const data = await res.json();
+
+ setJobTemplates(data.templates);
+ } catch (error) {
+ toast.error('Error fetching Templates');
+ }
+ };
+
+ const fetchJobFormsAll = async () => {
+ try {
+ // eslint-disable-next-line no-console
+ console.log(`${ENDPOINTS.GET_ALL_JOB_FORMS}`);
+ const response = await fetch(`${ENDPOINTS.GET_ALL_JOB_FORMS}`, {
+ method: 'GET',
+ headers: {
+ Authorization: localStorage.getItem('token'),
+ },
+ });
+ if (!response.ok) throw new Error(`Failed to fetch all jobForms: ${response.statusText}`);
+ // eslint-disable-next-line no-console
+ console.log(response);
+ const data = await response.json();
+ setJobFormsAll(data.forms);
+ } catch (error) {
+ toast.error('Error fetching jobFormsAll');
+ }
+ };
+
+ const fetchPositions = async categoryInput => {
+ try {
+ const response = await fetch(
+ `${ENDPOINTS.JOB_POSITIONS}/?category=${encodeURIComponent(categoryInput)}`,
+ {
+ method: 'GET',
+ },
+ );
+ if (!response.ok) {
+ throw new Error(`Failed to fetch positions: ${response.statusText}`);
+ }
+
+ const data = await response.json();
+ const sortedPositions = data.positions.sort((a, b) => a.localeCompare(b));
+ setPositions(sortedPositions);
+ } catch (error) {
+ toast.error('Error fetching positions');
+ }
+ };
+
+ const handleSubmit = event => {
+ event.preventDefault();
+ console.log('formData');
+ console.log(formData);
+ if (!formData.category) {
+ setErrors({ category: 'Category is required' });
+ toast.error('Category is required');
+ return;
+ }
+ if (!formData.title) {
+ setErrors({ title: 'Title is required' });
+ toast.error('Title is required');
+ return;
+ }
+
+ if (!formData.description) {
+ setErrors({ description: 'Description is required' });
+ toast.error('Description is required');
+ return;
+ }
+ //
+ const descriptionWordCount = getWordCount(formData.description);
+ // eslint-disable-next-line no-console
+ console.log(`word count ${descriptionWordCount}`);
+
+ if (descriptionWordCount < 30) {
+ setErrors({ description: 'Description must be at least 30 characters long' });
+ toast.error('Description must be at least 30 characters long');
+ textareaRef.current?.focus();
+ return;
+ }
+
+ /* if (!formData.about) {
+ setErrors({ about: 'About is required' });
+ toast.error('About is required');
+ return;
+ }
+ //
+ const aboutWordCount = getWordCount(formData.about);
+ // eslint-disable-next-line no-console
+ console.log(`word count ${aboutWordCount}`);
+
+ if (aboutWordCount < 30) {
+ setErrors({ about: 'About must be at least 30 words long' });
+ toast.error('About must be at least 30 words long');
+ textareaRef.current?.focus();
+ return;
+ } */
+ if (!formData.requirements) {
+ setErrors({ requirements: 'Requirements is required' });
+ toast.error('Requirements is required');
+ return;
+ }
+ //
+ const requirementsWordCount = getWordCount(formData.requirements);
+ // eslint-disable-next-line no-console
+ console.log(`word count ${requirementsWordCount}`);
+
+ if (requirementsWordCount < 30) {
+ setErrors({ requirements: 'Requirements must be at least 30 words long' });
+ toast.error('Requirements must be at least 30 words long');
+ textareaRef.current?.focus();
+ return;
+ }
+ if (!formData.projects) {
+ setErrors({ projects: 'Projects is required' });
+ toast.error('Projects is required');
+ return;
+ }
+ //
+ const projectsWordCount = getWordCount(formData.projects);
+ // eslint-disable-next-line no-console
+ console.log(`word count ${projectsWordCount}`);
+
+ if (projectsWordCount < 1) {
+ setErrors({ projects: 'Projects must be at least 1 word long' });
+ toast.error('Projects must be at least 1 word long');
+ textareaRef.current?.focus();
+ return;
+ }
+ if (!formData.ourCommunity) {
+ setErrors({ ourCommunity: 'Our Community is required' });
+ toast.error('Our Community is required');
+ return;
+ }
+ //
+ const ourCommunityWordCount = getWordCount(formData.ourCommunity);
+ // eslint-disable-next-line no-console
+ console.log(`word count ${ourCommunityWordCount}`);
+
+ if (ourCommunityWordCount < 30) {
+ setErrors({ ourCommunity: 'Our Community must be at least 30 words long' });
+ toast.error('Our Community must be at least 30 words long');
+ textareaRef.current?.focus();
+ return;
+ }
+
+ if (!formData.imageUrl) {
+ setErrors({ imageUrl: 'ImageURL is required' });
+ toast.error('ImageURL is required');
+ return;
+ }
+
+ if (!formData.imageUrl || !isValidDropboxImageUrl(formData.imageUrl)) {
+ setErrors({ imageUrl: 'Enter a valid ImageURL' });
+ toast.error('Enter a valid ImageURL');
+ return;
+ }
+ if (!formData.location) {
+ setErrors({ location: 'Location is required' });
+ toast.error('Location is required');
+ return;
+ }
+ if (formData.location !== 'remote') {
+ setErrors({ location: 'Location should be remote only' });
+ toast.error('Location should be remote only');
+ return;
+ }
+
+ if (!formData.applyLink) {
+ setErrors({ applyLink: 'Apply Link is required' });
+ toast.error('Apply Link is required');
+ return;
+ }
+ // eslint-disable-next-line no-console
+ console.log('formData.applyLink');
+ // eslint-disable-next-line no-console
+ console.log(formData.applyLink);
+ // eslint-disable-next-line no-console
+ console.log(isValidUrl(applyLink));
+ if (!formData.applyLink || !isValidUrl(formData.applyLink)) {
+ setErrors({ applyLink: 'Enter the valid Apply Link' });
+ toast.error('Enter the valid Apply Link');
+ return;
+ }
+ // eslint-disable-next-line no-console
+ console.log(formData.jobDetailsLink);
+ // eslint-disable-next-line no-console
+ console.log(isValidUrl(formData.jobDetailsLink));
+
+ const emptyMsg = '';
+ setErrors(emptyMsg);
+ submitJobAds();
+ setFormData({ ...initialState });
+ };
+
+ const handleCancel = event => {
+ event.preventDefault();
+ const emptyMsg = '';
+ setErrors(emptyMsg);
+ setFormData({ ...initialState });
+ };
+
+ const handleChange = event => {
+ const { name, value } = event.target;
+ setFormData(prev => ({ ...prev, [name]: value }));
+ // Clear error for this specific field automatically
+ setErrors(prev => ({
+ ...prev,
+ [name]: '',
+ }));
+ if (name === 'category') {
+ if (value === '') {
+ setPositions([]);
+ return;
+ }
+ fetchPositions(value);
+ }
+ if (name === 'applyLink') {
+ // eslint-disable-next-line no-console
+ console.log('APPLYLINK');
+
+ // eslint-disable-next-line no-console
+ console.log(value);
+ }
+ };
+
+ useEffect(() => {
+ fetchCategories();
+ // fetchPositions();
+ fetchJobFormsAll();
+ fetchTemplates();
+ }, []);
+
+ return (
+
+ {canCreateCollabJobAds === false ? (
+
You do not have permission to create Collaboration Job Ads.
+ ) : canCreateCollabJobAds === true ? (
+ <>
+
+
+
Collaboration Ads Creation
+
+
+
+ >
+ ) : (
+ ''
+ )}
+
+ );
+}
+
+export default JobAdsCreation;
diff --git a/src/components/Collaboration/JobAdsCreation.module.css b/src/components/Collaboration/JobAdsCreation.module.css
new file mode 100644
index 0000000000..b4cae32e41
--- /dev/null
+++ b/src/components/Collaboration/JobAdsCreation.module.css
@@ -0,0 +1,212 @@
+.jobAds-header {
+ display:flex;
+ justify-content: center;
+ align-items: center;
+}
+.jobAds-creation {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ width: 100%;
+ margin: 0 auto;
+ padding: 20px;
+ gap:20px;
+ background-color: #f9f9f9;
+}
+.jobAds-creation .header img {
+ height: auto;
+ margin: 0 auto;
+ flex-direction: column;
+
+}
+.jobAds-creation .h3 {
+ justify-content: center;
+ display:flex;
+ align-items: center;
+}
+.title-header {
+ display: flex;
+ justify-content: center;
+}
+.input-error {
+ display: flex;
+ flex-direction: row;
+ align-items: flex-start; /*center;
+ /* justify-content: center; */
+ /* width: 100%; */
+ width: 1000px;
+ padding-left: 50px;
+ padding-top:10px;
+ margin-left:50px;
+/* background-color: aliceblue; */
+}
+.input-item{
+ display:flex;
+ flex-direction: row;
+ align-items: flex-start;
+ justify-content:center;
+ margin-bottom: 1rem;
+ /* text-align: center; */
+ text-align:left;
+
+ background-color: blueviolet;
+}
+.input-label {
+ display: flex;
+ align-items: center;
+ width:200px;
+ text-align:justify; /*center;
+ background-color: #445A77; */
+ }
+.jobAds-input{
+max-width: 100%;
+width: 700px;
+/* background-color: #1E88E5; */
+}
+/*textarea {
+ width:100%;
+ height:auto;
+ min-height:150px;
+ background-color: aquamarine;
+}*/
+input {
+ width:100%;
+ height:30px;
+}
+.error { color: red;
+ font-size: 0.9em;
+ margin-top: 5px;
+ margin-bottom: 10px;
+ text-align: center;
+}
+.jobAds-creation-button-group {
+ margin-top:20px;
+ display: flex;
+ width: 90%;
+ justify-content: space-evenly;
+}
+.submit-button,.cancel-button {
+ /*padding: 10px 20px; */
+ padding: 10px;
+ font-size: 1em;
+ cursor: pointer;
+ transition: background 0.2s ease;
+
+}
+.jobAds-creation-container {
+ display: flex;
+ flex-direction: column;
+ justify-items: center;
+ width: 90%;
+ margin: 0 auto;
+ background-color: #fff;
+ border: 1px solid #ddd;
+}
+
+
+.user-collaboration-dark-mode {
+ background-color: #121212; /*#1B2A41;*/
+ color: #E0E0E0; /* #f1f1f1; */
+}
+.user-collaboration-dark-mode .jobAds-creation-container {
+ background-color: #1E1E1E;
+}
+.user-collaboration-dark-mode .jobAds-creation-container .jobAds-creation-button-group{
+ background-color:#2A2A2A;
+ /* #32455A; /* lighter gray-blue background */
+ color:#E0E0E0;
+ border: 1px solid #445A77; /* optional for definition */
+
+}
+
+/* Title */
+.user-collaboration-dark-mode h2 {
+ text-align: center;
+ color: #1E88E5; /* accent blue */
+ margin-bottom: 2rem;
+}
+
+/* Labels */
+.user-collaboration-dark-mode label {
+ color: #B0BEC5; /* muted gray for labels */
+ }
+
+ /* Inputs & Selects */
+.user-collaboration-dark-mode input,
+.user-collaboration-dark-mode select,
+.user-collaboration-dark-mode textarea {
+ background-color: #2A2A2A;
+ color: #E0E0E0;
+}
+.user-collaboration-dark-mode .jobAds-creation-container .input-label{
+ background-color:transparent; /* #2E3A4D; /* slightly lighter than main bg */
+ color:#A0A0A0; /* #f1f1f1; /* keep text readable */
+}
+.user-collaboration-dark-mode textarea::placeholder,
+.user-collaboration-dark-mode select::placeholder,
+.user-collaboration-dark-mode input::placeholder
+{
+
+ color: #888; /* softer placeholders */
+}
+.user-collaboration-dark-mode .jobAds-creation-button-group .submit-button {
+ background-color: #1E88E5;
+ color: #fff;
+ border: none;
+ padding: 0.7rem 1.5rem;
+ border-radius: 6px;
+ cursor: pointer;
+ font-weight: bold;
+ transition: background 0.2s ease;
+}
+
+.user-collaboration-dark-mode .jobAds-creation-button-group .submit-btn:hover {
+ background-color: #1565C0; /* darker blue on hover */
+}
+
+/* Cancel Button */
+.user-collaboration-dark-mode .jobAds-creation-button-group .cancel-btn {
+ background-color: #555;
+ color: #fff;
+ border: none;
+ padding: 0.7rem 1.5rem;
+ border-radius: 6px;
+ cursor: pointer;
+ font-weight: bold;
+ transition: background 0.2s ease;
+}
+
+.user-collaboration-dark-mode .jobAds-creation-button-group .cancel-btn:hover {
+ background-color: #666;
+}
+
+@media (max-width: 768px) {
+ .jobAds-creation {
+ padding: 10px;
+ }
+ .jobAds-input {
+ width: 100%;
+ }
+ .input-error {
+ width: 100%;
+ }
+ .input-item {
+ flex-direction: column;
+ align-items: center;
+ }
+ .input-label {
+ width: 100px;
+ font-size: 0.9em;
+ }
+ .submit-button, .cancel-button {
+ width: 100px;
+ font-size: 0.9em;
+ padding: 8px 16px;
+ }
+ .jobAds-creation-container {
+ width: 100%;
+ padding-top: 10px;
+ padding-bottom: 50px;
+ }
+}
\ No newline at end of file
diff --git a/src/components/Collaboration/JobApplyLink.jsx b/src/components/Collaboration/JobApplyLink.jsx
new file mode 100644
index 0000000000..b98be3e893
--- /dev/null
+++ b/src/components/Collaboration/JobApplyLink.jsx
@@ -0,0 +1,215 @@
+import { Route, useParams } from 'react-router-dom';
+import { useSelector } from 'react-redux';
+import { useEffect, useState } from 'react';
+
+import { toast } from 'react-toastify';
+import { ENDPOINTS } from '../../utils/URL';
+
+//import { ApiEndpoint } from '../../utils/URL';
+import OneCommunityImage from '../../assets/images/logo2.png';
+import styles from '../Collaboration/JobApplyLink.module.css';
+
+function JobApplyLink() {
+ const { formId } = useParams();
+ const [jobFormsAll, setJobFormsAll] = useState([]);
+
+ const [jobForms, setJobForms] = useState([]);
+
+ const [loading, setLoading] = useState(false);
+ const [applyLink, setApplyLink] = useState('');
+ const fetchJobFormsAll = async () => {
+ try {
+ // eslint-disable-next-line no-console
+ console.log(`${ENDPOINTS.GET_ALL_JOB_FORMS}`);
+ const response = await fetch(`${ENDPOINTS.GET_ALL_JOB_FORMS}`, {
+ method: 'GET',
+ headers: {
+ Authorization: localStorage.getItem('token'),
+ },
+ });
+ if (!response.ok) throw new Error(`Failed to fetch all jobForms: ${response.statusText}`);
+ // eslint-disable-next-line no-console
+ console.log(response);
+ const data = await response.json();
+ setJobFormsAll(data.forms);
+ } catch (error) {
+ toast.error('Error fetching jobFormsAll');
+ }
+ };
+ useEffect(() => {
+ fetchJobFormsAll();
+ }, []);
+
+ const getJobForms = async () => {
+ // console.log(`formId: ${formId}`);
+ console.log(`applyLink:${applyLink}`);
+ const formId = new URL(applyLink).pathname.split('/').pop();
+
+ try {
+ setLoading(true);
+ /*console.log(`res is ${ENDPOINTS.APIEndpoint()}/jobforms/${formId}`);
+ const response = await fetch(`${ENDPOINTS.APIEndpoint()}/jobforms/${formId}`, {
+ method: 'get',
+ headers: {
+ Authorization: localStorage.getItem('token'),
+ },
+ });
+ */
+ console.log(`res is ${ENDPOINTS.APIEndpoint()}/jobforms/${formId}`);
+ const response = await fetch(`${ENDPOINTS.APIEndpoint()}/jobforms/${formId}`, {
+ method: 'get',
+ headers: {
+ Authorization: localStorage.getItem('token'),
+ },
+ });
+
+ console.log(response);
+ if (!response.ok) throw new Error(`Failed to fetch all Templates: ${response.statusText}`);
+
+ const data = await response.json();
+ console.log(data);
+ // console.log(data.template);
+ // console.log(data.template.fields.length);
+
+ setJobForms(data);
+ // console.log(jobTemplate);
+ // console.log(jobTemplate.template.fields.length);
+ setLoading(false);
+ } catch (error) {
+ toast.error('Error fetching JobForms');
+ }
+ };
+
+ useEffect(() => {
+ console.log(`before calling getTemplate`);
+ getJobForms();
+ }, []);
+ const darkMode = useSelector(state => state.theme.darkMode);
+
+ const handleSubmit = e => {
+ e.preventDefault();
+ alert('form submitted');
+ /* try {
+ setLoading(true);
+ console.log(`res is ${ENDPOINTS.APIEndpoint()}/jobforms/${formId}`);
+ const response = await fetch(`${ENDPOINTS.APIEndpoint()}/jobforms/${formId}`, {
+ method: 'get',
+ headers: {
+ Authorization: localStorage.getItem('token'),
+ },
+ });
+ console.log(response);
+ if (!response.ok) throw new Error(`Failed to fetch all Templates: ${response.statusText}`);
+
+ const data = await response.json();
+ console.log(data);
+ // console.log(data.template);
+ // console.log(data.template.fields.length);
+ }*/
+ };
+ const handleChange = event => {
+ const { name, value } = event.target;
+ // eslint-disable-next-line no-console
+ console.log(value);
+ setApplyLink(value);
+ };
+ useEffect(() => {
+ console.log(`before calling getJobForms`);
+ getJobForms();
+ }, [applyLink]);
+
+ const resetForm = e => {
+ alert('form cancelled');
+ };
+ return !loading ? (
+
+
+
+
+
{jobForms.form && jobForms.form.title}
+
{jobForms.form && jobForms.form.description}
+
+
+
+ ) : (
+ 'Loading '
+ );
+}
+export default JobApplyLink;
diff --git a/src/components/Collaboration/JobApplyLink.module.css b/src/components/Collaboration/JobApplyLink.module.css
new file mode 100644
index 0000000000..e718aaca14
--- /dev/null
+++ b/src/components/Collaboration/JobApplyLink.module.css
@@ -0,0 +1,33 @@
+
+.lightModeContainer {
+ background-color:#ffffff;
+ color:#000000;
+ margin:10px;
+ padding:10px;
+
+}
+.darkModeContainer {
+ background-color:#1e1e1e;
+ color:#ffffff;
+ margin:10px;
+ padding:10px;
+}
+.ApplyLink-header{
+ display:flex;
+ flex-direction: column;;
+ align-items: center;
+}
+.buttonGroup{
+ display:flex;
+ flex-direction: row;
+ justify-content:space-around;
+ gap:3px;
+ padding:15px;
+ margin:50px;
+ border-radius: 5px;
+ border: solid 2px #000000;
+}
+.buttonGroup button{
+ border:5px;
+}
+
diff --git a/src/components/Collaboration/JobDetailsLink.jsx b/src/components/Collaboration/JobDetailsLink.jsx
new file mode 100644
index 0000000000..aaff125c72
--- /dev/null
+++ b/src/components/Collaboration/JobDetailsLink.jsx
@@ -0,0 +1,584 @@
+import { Route, useParams } from 'react-router-dom';
+import { useSelector } from 'react-redux';
+import { useEffect, useState } from 'react';
+import axios from 'axios';
+
+import { toast } from 'react-toastify';
+import { ApiEndpoint } from '~/utils/URL';
+import { ENDPOINTS } from '../../utils/URL';
+
+import OneCommunityImage from '../../assets/images/logo2.png';
+import styles from '../Collaboration/JobDetailsLink.module.css';
+
+function JobDetailsLink() {
+ const { givenId } = useParams();
+ const initialState = {
+ formId: '',
+ // questions: [],
+ answers: [],
+ };
+ const [formData, setFormData] = useState({ ...initialState });
+
+ const darkMode = useSelector(state => state.theme.darkMode);
+ const [jobsDetail, setJobsDetail] = useState([]);
+
+ const [jobsDetailById, setJobsDetailById] = useState([]);
+ const [loading, setLoading] = useState();
+
+ const [jobForms, setJobForms] = useState([]);
+ const [uploadingFiles, setUploadingFiles] = useState({});
+ const [errors, setErrors] = useState({});
+
+ const [resumeFile, setResumeFile] = useState(null);
+ const [uploadedFile, setUploadedFile] = useState();
+ const [uploadSuccess, setUploadSuccess] = useState(false);
+ const getJobDetails = async (givenCategory, givenPosition) => {
+ setLoading(true);
+ // Note: route params from the jobDetailsLink are URL-encoded (e.g. %26, %2F).
+ // We decode them to get plain text values ("Creative & Media", "Photoshop/Graphic Designer")
+ // and then re-encode once when building the API URL to avoid double-encoding (e.g. %252F).
+
+ const decodedCategory = decodeURIComponent(givenCategory);
+ const decodedPosition = decodeURIComponent(givenPosition);
+ // eslint-disable-next-line no-console
+ console.log(`category: ${decodeURIComponent(givenCategory)}`);
+ // eslint-disable-next-line no-console
+ console.log(`position: ${decodeURIComponent(givenPosition)}`);
+
+ try {
+ const response = await fetch(
+ `${ApiEndpoint}/jobs?
+ category=${encodeURIComponent(decodedCategory)}
+ &position=${encodeURIComponent(decodedPosition)}`,
+ {
+ method: 'GET',
+ },
+ );
+ // eslint-disable-next-line no-console
+ console.log(response);
+ if (!response.ok) {
+ throw new Error(`Failed to fetch jobs: ${response.statusText}`);
+ }
+
+ const data = await response.json();
+ // eslint-disable-next-line no-console
+ console.log(data.jobs);
+ setJobsDetail(data.jobs);
+ setLoading(false);
+ } catch (error) {
+ toast.error('Error fetching jobs Details');
+ }
+ };
+
+ const getJobDetailsById = async id => {
+ setLoading(true);
+
+ const givenIdDecoded = decodeURIComponent(givenId);
+ // eslint-disable-next-line no-console
+ console.log(`givenIdDecoded: ${decodeURIComponent(givenIdDecoded)}`);
+
+ try {
+ const response = await fetch(`${ApiEndpoint}/jobs/${id}`, {
+ method: 'GET',
+ });
+ // eslint-disable-next-line no-console
+ console.log(response);
+ if (!response.ok) {
+ throw new Error(`Failed to fetch jobs: ${response.statusText}`);
+ }
+
+ const data = await response.json();
+ // eslint-disable-next-line no-console
+ console.log(data);
+ setJobsDetailById(data);
+
+ // getJobForms(jobsDetailById.applyLink);
+ setLoading(false);
+ } catch (error) {
+ toast.error('Error fetching jobs Details');
+ }
+ };
+
+ const getJobForms = async applyLink => {
+ // eslint-disable-next-line no-console
+ console.log(applyLink);
+ const formId = applyLink.split('jobforms/')[1];
+ // eslint-disable-next-line no-console
+ console.log(formId);
+ // eslint-disable-next-line no-console
+ console.log(`formId: ${formId}`);
+
+ try {
+ // setLoading(true);
+ // eslint-disable-next-line no-console
+ console.log(`res is ${ENDPOINTS.APIEndpoint()}/jobforms/${formId}`);
+ const response = await fetch(`${ENDPOINTS.APIEndpoint()}/jobforms/${formId}`, {
+ method: 'get',
+ });
+ // eslint-disable-next-line no-console
+ console.log(response);
+ if (!response.ok) throw new Error(`Failed to fetch all jobForms : ${response.statusText}`);
+
+ const data = await response.json();
+ // eslint-disable-next-line no-console
+ console.log(data);
+
+ setJobForms(data);
+ } catch (error) {
+ // eslint-disable-next-line no-console
+ console.log('error');
+ // eslint-disable-next-line no-console
+ console.log(error);
+ toast.error('Error fetching JobForms');
+ }
+ };
+
+ useEffect(() => {
+ getJobDetailsById(givenId);
+ if (!loading && jobsDetailById?.applyLink) getJobForms(jobsDetailById.applyLink);
+ }, []);
+
+ useEffect(() => {
+ if (!loading && jobsDetailById?.applyLink) getJobForms(jobsDetailById.applyLink);
+ }, [loading, jobsDetailById.applyLink]);
+
+ useEffect(() => {
+ if (!loading && jobsDetailById?.applyLink) {
+ const applyLinkFormId = jobsDetailById?.applyLink.split('jobforms/')[1];
+ // eslint-disable-next-line no-console
+ console.log(applyLinkFormId);
+ setFormData(prev => ({ ...prev, formId: applyLinkFormId }));
+ }
+ }, [loading, jobsDetailById.applyLink]);
+
+ const getValue = name => {
+ if (!Array.isArray(formData.answers)) return ''; // ✅ fallback
+ const found = formData.answers?.find(a => a.questionId === name || a.label === name);
+ return found ? found.answer : '';
+ };
+ const handleChange = (event, idx) => {
+ const { id, name, value } = event.target;
+
+ setFormData(prev => ({
+ ...prev,
+ answers: Array.isArray(prev.answers)
+ ? [
+ ...prev.answers.filter(a => a.questionId !== id),
+ { questionId: id, questionText: name, answer: value, order: idx },
+ ]
+ : [{ questionId: id, questionText: name, answer: value, order: idx }],
+ }));
+ };
+
+ const handleFileChange = async event => {
+ const { id, name } = event.target;
+ console.log(`name is ${event.target.name}`);
+
+ console.log(`name is ${event.target.files[0].name}`);
+ const selFile = event.target.files[0];
+ if (!selFile) return;
+ if (selFile.size > 5 * 1024 * 1024) {
+ toast.error('File size exceeds 5MB limit. Please choose a smaller file. ');
+ selFile.value = null;
+ return;
+ }
+ if (
+ ![
+ 'application/pdf',
+ 'application/doc',
+ 'application/docx',
+ 'image/jpeg',
+ 'image/png',
+ 'image/bmp',
+ ].includes(selFile.type)
+ ) {
+ toast.error('Invalid file type. Please upload a PDF, DOC, DOCX, JPG, PNG, or BMP file.');
+ selFile.value = null;
+
+ return;
+ }
+ try {
+ setUploadingFiles(prev => ({ ...prev, [name]: true }));
+ console.log(uploadingFiles);
+
+ const formResumeData = new FormData();
+ formResumeData.append('file', selFile);
+ // eslint-disable-next-line no-console
+ console.log(`res is ${ENDPOINTS.APIEndpoint()}/jobforms/responses/upload`);
+
+ const formResumeDataResponse = await axios.post(
+ `${ENDPOINTS.APIEndpoint()}/jobforms/responses/upload`,
+ formResumeData,
+ {
+ headers: {
+ 'Content-Type': 'multipart/form-data',
+ },
+ },
+ );
+
+ // eslint-disable-next-line no-console
+ console.log('formResumeDataResponse');
+ // eslint-disable-next-line no-console
+ console.log(formResumeDataResponse);
+
+ const responseData = await formResumeDataResponse.data;
+ // eslint-disable-next-line no-console
+ console.log('data');
+ // eslint-disable-next-line no-console
+ console.log(responseData);
+ console.log(responseData?.data?.url);
+ const dropboxLink = responseData?.data?.url;
+ setFormData(prev => ({
+ ...prev,
+ answers: Array.isArray(prev.answers)
+ ? [
+ ...prev.answers.filter(a => a.questionId !== id),
+ { questionId: id, questionText: name, answer: dropboxLink },
+ ]
+ : [{ questionId: id, questionText: name, answer: dropboxLink }],
+ }));
+ setUploadingFiles(prev => ({ ...prev, [name]: false }));
+ console.log(uploadingFiles);
+ } catch (err) {
+ console.error('Upload failed', err);
+ let errorMessage = 'File upload failed.';
+ if (err.response) {
+ console.log('Backend response', err.response.data);
+ errorMessage = err.response.data?.message || `Server error (${err.response.status})`;
+ toast.error(errorMessage);
+ } else if (err.request) {
+ console.log('No response received');
+ errorMessage = 'No response from server. Check your connection.';
+ } else {
+ console.error('Request Error', err.request);
+ errorMessage = err.message;
+ }
+ console.log('err');
+ console.log(err);
+ toast.error(errorMessage);
+ setUploadingFiles(prev => ({ ...prev, [name]: false }));
+ console.log(uploadingFiles);
+ }
+ };
+
+ const handleUpload = async () => {
+ alert('Handle Upload');
+ console.log(resumeFile);
+ // if (!resumeFile) return alert('select a file');
+ const formResumeData = new FormData();
+ formResumeData.append('file', resumeFile);
+ // eslint-disable-next-line no-console
+ console.log(`res is ${ENDPOINTS.APIEndpoint()}/jobforms/responses/upload`);
+
+ const formResumeDataResponse = await axios.post(
+ `${ENDPOINTS.APIEndpoint()}/jobforms/responses/upload`,
+ formResumeData,
+ {
+ headers: {
+ 'Content-Type': 'multipart/form-data',
+ },
+ },
+ );
+
+ // eslint-disable-next-line no-console
+ console.log('formResumeDataResponse');
+ // eslint-disable-next-line no-console
+ console.log(formResumeDataResponse);
+
+ const responseData = await formResumeDataResponse.data;
+ // eslint-disable-next-line no-console
+ console.log('data');
+ // eslint-disable-next-line no-console
+ console.log(responseData);
+ console.log(responseData.data.url);
+ alert(`data.url`);
+ };
+
+ const submitJobforms = async () => {
+ // eslint-disable-next-line no-console
+ console.log('inside submitJobForms');
+ // eslint-disable-next-line no-console
+ console.log(formData);
+
+ try {
+ setLoading(true);
+
+ // eslint-disable-next-line no-console
+ console.log(`res is ${ENDPOINTS.APIEndpoint()}/jobforms/responses`);
+
+ const response = await axios.post(`${ENDPOINTS.APIEndpoint()}/jobforms/responses`, formData);
+ // eslint-disable-next-line no-console
+ console.log('response');
+ // eslint-disable-next-line no-console
+ console.log(response);
+
+ const data = await response.data;
+ // eslint-disable-next-line no-console
+ console.log('data');
+ // eslint-disable-next-line no-console
+ console.log(data);
+
+ setLoading(false);
+ setFormData({ ...initialState });
+ toast.success('Responses submitted successfully');
+ } catch (error) {
+ // If server responded with error (4xx or 5xx)
+ if (error.response) {
+ console.error(error.response.status);
+ console.error(error.response.data);
+ toast.error(error.response.status);
+ } else if (error.request) {
+ console.error('No response:', error.request);
+ toast.error('No response from server. Check your connection.');
+ } else {
+ console.log(error);
+ toast.error('Failed to submit responses');
+ }
+ }
+ };
+ const inputValidation = () => {
+ //check all the inputs are filled
+ console.log('jobForms.questions.length');
+ console.log(jobForms.form.questions.length);
+ console.log(formData.answers.length);
+ if (!jobForms?.form?.questions || !formData?.answers) {
+ console.error('Missing form structure or answers data.');
+ return false;
+ }
+ console.log('heree');
+ // if (formData.answers.map(a => a.answer).includes('')) return false;
+ console.log(formData.answers.length);
+ // loop through jobForms.form.questions and check if each questionId is present in formsData.answers
+ for (let i = 0; i < jobForms.form.questions.length; i++) {
+ console.log(`i is ${i}`);
+ console.log(jobForms.form.questions[i]);
+ console.log(jobForms.form.questions[i].isRequired);
+
+ const questionId = jobForms.form.questions[i]._id;
+ const answerObj = formData.answers.find(a => a.questionId === questionId);
+ if ((!answerObj || !answerObj.answer) && jobForms.form.questions[i].isRequired) {
+ setErrors({
+ [jobForms.form.questions[i]
+ .questionText]: `${jobForms.form.questions[i].questionText} is required`,
+ });
+ console.log('errors');
+ console.log(errors);
+ toast.error(`${jobForms.form.questions[i].questionText} is required`);
+
+ return false;
+ } else {
+ setErrors({
+ [jobForms.form.questions[i].questionText]: ``,
+ });
+ }
+ }
+ return true;
+ };
+
+ const handleSubmit = e => {
+ console.log(formData);
+
+ e.preventDefault();
+ // inputValidation();
+ if (!inputValidation()) {
+ return;
+ }
+ submitJobforms();
+ };
+ const resetForm = e => {
+ alert('form cancelled');
+ };
+ useEffect(() => {
+ console.log('updated errors:', errors);
+ }, [errors]);
+
+ return (
+
+
+ {!loading ? (
+
+

+
+ {`Job Details for Category: ${jobsDetailById.category},
+ Position: ${jobsDetailById.title}`}
+
+ {['description', 'requirements', 'projects', 'ourCommunity'].map(
+ key =>
+ jobsDetailById[key] && (
+
+ ),
+ )}
+ ;
+
+
+ ) : (
+ 'Loading '
+ )}
+
+ );
+}
+
+export default JobDetailsLink;
diff --git a/src/components/Collaboration/JobDetailsLink.module.css b/src/components/Collaboration/JobDetailsLink.module.css
new file mode 100644
index 0000000000..5bae627d69
--- /dev/null
+++ b/src/components/Collaboration/JobDetailsLink.module.css
@@ -0,0 +1,151 @@
+.job-details-landing {
+ display:flex;
+ flex-direction:column;
+ flex-wrap: wrap;
+ align-content: center;
+}
+.job-details-header {
+ display:flex;
+ justify-content: center;
+ align-items: center;
+}
+
+.job-details-container {
+ display:flex;
+ width: 90%;
+ margin: 0 auto;
+ flex-direction: column;
+ align-items: stretch; /* center */
+ background-color: #fff;
+ border: 1px solid #ddd;
+ /* border-radius: 10px; */
+}
+.job-details-card {
+ display:flex;
+ flex-direction: column;
+ /* flex-wrap:wrap;
+ /*width:70%; */
+ border: 1px solid #ddd;
+ margin:10px;
+ padding:10px;
+ /*justify-content:center;
+ align-items: center; */
+
+ text-align: justify;
+ font-weight: 500;
+ font-size: 1.5rem;
+ line-height: 1.6;
+ /* width: 100%; */
+}
+.job-details-card p {
+ font-size: 30px;
+}
+.job-details-card ul {
+ text-align: left;
+ padding-left: 1.5rem;
+ list-style-position: outside; /* keep bullets outside text */
+ }
+.job-details-image {
+ width:100%;
+ height:100%;
+}
+.lightModeContainer {
+ background-color:#ffffff;
+ color:#000000;
+ margin:10px;
+ padding:10px;
+
+}
+.darkModeContainer {
+ background-color:#1e1e1e;
+ color:#ffffff;
+ margin:10px;
+ padding:10px;
+}
+.ApplyLink-header{
+ display:flex;
+ flex-direction: column;;
+ align-items: center;
+}
+.buttonGroup{
+ display:flex;
+ flex-direction: row;
+ justify-content:space-around;
+ gap:3px;
+ padding:15px;
+ margin:50px;
+ border-radius: 5px;
+ border: solid 2px #000000;
+}
+.buttonGroup button{
+ border:5px;
+}
+.input-error {
+ display: flex;
+ flex-direction: column;
+ gap:10px;
+ width:1000px;
+}
+iframe {
+ display:flex;
+}
+h1 {
+ width:100%;
+ margin:0 auto;
+}
+h1 img,
+h2 img,
+h3 img,
+h4 img,
+h5 img,
+h6 img,
+p img {
+ display: block;
+ height:auto;
+ width:100%;
+ max-width: none;
+ }
+@media (max-width: 768px) {
+h1 img,
+h2 img,
+h3 img,
+h4 img,
+h5 img,
+h6 img,
+p img {
+ display: block;
+ height:auto;
+ width:100%;
+ max-width:none;
+}
+}
+.job-details-image-card {
+ display: block;
+ height:auto;
+ width:100%;
+ max-width: none;
+}
+.input-error {
+ display: flex;
+ flex-direction: column;
+}
+.upload-button {
+ display: flex;
+}
+.job-form-questions {
+ display: flex;
+ flex-direction: column;
+ width: 70%;
+ margin: 10px;
+ padding:10px;
+ justify-items: center;
+ gap: 30px;
+}
+.user-input {
+ display:flex;
+ flex-direction: row;
+}
+.error-message {
+ color: red;
+ font-size: 0.9rem;
+}
\ No newline at end of file
diff --git a/src/components/PermissionsManagement/PermissionsConst.jsx b/src/components/PermissionsManagement/PermissionsConst.jsx
index 00a1eb252c..691a182cee 100644
--- a/src/components/PermissionsManagement/PermissionsConst.jsx
+++ b/src/components/PermissionsManagement/PermissionsConst.jsx
@@ -642,6 +642,17 @@ export const permissionLabels = [
},
],
},
+ {
+ label: 'CollabJobAds',
+ description: 'Collaboration Job Ads related permissions',
+ subperms: [
+ {
+ label: 'Create CollabJobAds',
+ key: 'createCollabJobAds',
+ description: 'Gives the user permission to cr.eate CollabJobAds',
+ },
+ ],
+ },
];
export const permissionLabelKeyMappingObj = generatePermissionLabelKeyMapping(permissionLabels, 0);
diff --git a/src/reducers/collaborationAdsReducer.js b/src/reducers/collaborationAdsReducer.js
new file mode 100644
index 0000000000..12a50702dd
--- /dev/null
+++ b/src/reducers/collaborationAdsReducer.js
@@ -0,0 +1,30 @@
+import {
+ CREATE_COLLABORATION_ADS_REQUEST,
+ CREATE_COLLABORATION_ADS_SUCCESS,
+ CREATE_COLLABORATION_ADS_FAIL,
+} from '../actions/collaborationAdsActions';
+const initialState = {
+ title: '',
+ category: '',
+ description: '',
+ imageUrl: '',
+ location: '',
+ applyLink: '',
+ jobDetailsLink: '',
+};
+
+/* eslint-disable-next-line default-param-last */
+const collaborationAdsReducer = (state = initialState, action) => {
+ switch (action.type) {
+ case CREATE_COLLABORATION_ADS_REQUEST:
+ return { ...state, loading: true, error: null };
+ case CREATE_COLLABORATION_ADS_SUCCESS:
+ return { ...state, loading: false, data: action.payload };
+ case CREATE_COLLABORATION_ADS_FAIL:
+ return { ...state, loading: false, error: action.error };
+ default:
+ return state;
+ }
+};
+
+export default collaborationAdsReducer;
diff --git a/src/routes.jsx b/src/routes.jsx
index 73a489e9ec..fbd01caa26 100644
--- a/src/routes.jsx
+++ b/src/routes.jsx
@@ -115,7 +115,9 @@ import TeamLocations from './components/TeamLocations';
import Inventory from './components/Inventory';
import Collaboration from './components/Collaboration';
import SuggestedJobsList from './components/Collaboration/SuggestedJobsList';
-
+import JobAdsCreation from './components/Collaboration/JobAdsCreation';
+import JobDetailsLink from './components/Collaboration/JobDetailsLink';
+import JobApplyLink from './components/Collaboration/JobApplyLink';
import TestEventRegistration from './components/EventRegistration/TestEventRegistration';
import MemberList from './components/QuestionnaireDashboard/MemberList';
import EventPopularity from './components/EventPopularity/EventPopularity';
@@ -252,6 +254,10 @@ const JobAnalyticsPage = lazy(() =>
);
const SuggestedJobsListBuilder = lazy(() => import('./components/Collaboration/SuggestedJobsList'));
+const JobAdsCreationBuilder = lazy(() => import('./components/Collaboration/JobAdsCreation'));
+const JobDetailsLinkBuilder = lazy(() => import('./components/Collaboration/JobDetailsLink'));
+const JobApplyLinkBuilder = lazy(() => import('./components/Collaboration/JobApplyLink'));
+
export default (
{/* ----- LB Dashboard Routing Starts----- */}
@@ -796,6 +802,9 @@ export default (
+
+
+
diff --git a/src/utils/URL.js b/src/utils/URL.js
index 0b6952e83d..5010d3fe29 100644
--- a/src/utils/URL.js
+++ b/src/utils/URL.js
@@ -465,6 +465,18 @@ export const ENDPOINTS = {
PROMOTION_ELIGIBILITY: `${APIEndpoint}/promotion-eligibility`,
PROMOTE_MEMBERS: `${APIEndpoint}/promote-members`,
+ // Collaboration - Job Ads endpoints
+ JOBS: `${APIEndpoint}/jobs`,
+ JOB_CATEGORIES: `${APIEndpoint}/jobs/categories`,
+ JOB_POSITIONS: `${APIEndpoint}/jobs/positions`,
+
+ // Collaboration - Jobforms endpoints
+ JOBFORMS_RESPONSES: `${APIEndpoint}/jobforms/responses`,
+
+ // Collaboration - Jobforms Upload endpoints
+ JOBFORMS_RESPONSES_UPLOAD: `${APIEndpoint}/jobforms/responses/upload`,
+
+
//pull requests analysis
PR_REVIEWS_INSIGHTS: `${APIEndpoint}/analytics/pr-review-insights`,
diff --git a/src/utils/checkValidURL.js b/src/utils/checkValidURL.js
index 8eb38c3373..35215f1b4f 100644
--- a/src/utils/checkValidURL.js
+++ b/src/utils/checkValidURL.js
@@ -9,3 +9,97 @@ export const isValidMediaUrl = url => {
const urlPattern = /^(?:https?:\/\/)?[\w.-]+\.[a-zA-Z]{2,}(?:\/\S*)?$/;
return urlPattern.test(trimmedUrl);
};
+
+export const isValidDropboxImageUrl= (string) => {
+ try {
+ const url = new URL(string);
+
+ // Must be http or https
+ if (!(url.protocol === "http:" || url.protocol === "https:")) {
+ return false;
+ }
+ // Must have a hostname (like example.com)
+ if (!url.hostname || url.hostname.indexOf(".") === -1 ) {
+ return false;
+ }
+
+ const validHosts =
+ ["www.dropbox.com", "dropbox.com",
+ "dl.dropboxusercontent.com",
+ "www.dropboxusercontent.com",]
+ if (!validHosts.includes(url.hostname)) {
+ return false;
+ }
+
+ // Extract pathname only (ignores ?raw=1)
+ const pathname = url.pathname.toLowerCase();
+
+ // Check extension from pathname
+ if (!pathname.match(/\.(jpg|jpeg|png|gif|webp)$/i)) return false;
+
+ return true;
+
+ } catch {
+ return false;
+ }
+}
+export const isValidDropboxDocUrl= (string) => {
+ try {
+ const url = new URL(string);
+
+ // Must be http or https
+ if (!(url.protocol === "http:" || url.protocol === "https:")) {
+ return false;
+ }
+ // Must have a hostname (like example.com)
+ if (!url.hostname || url.hostname.indexOf(".") === -1 ) {
+ return false;
+ }
+
+ const validHosts =
+ ["www.dropbox.com", "dropbox.com",
+ "dl.dropboxusercontent.com",
+ "www.dropboxusercontent.com",]
+ if (!validHosts.includes(url.hostname)) {
+ return false;
+ }
+
+ // Optionally: enforce file extension (doc, docx, pdf, etc.)
+ if (!url.pathname.match(/\.(doc|pdf|docx|odt|rtf|txt)$/i)) {
+ return false;
+ }
+
+ return true;
+ } catch {
+ return false;
+ }
+}
+
+export const isValidUrl= (string) => {
+ try {
+ const url = new URL(string);
+
+ // Must be http or https
+ if (!(url.protocol === "http:" || url.protocol === "https:")) {
+ return false;
+ }
+
+ // Must have a hostname (like example.com)
+ if (!url.hostname) {
+ return false;
+
+ }
+ // Allow localhost or IP addresses
+ const isLocalOrIp = url.hostname === "localhost" || /^[\d.]+$/.test(url.hostname);
+ const hasDot = url.hostname.includes(".");
+
+ if (!isLocalOrIp && !hasDot) {
+ return false;
+ }
+
+
+ return true;
+ } catch {
+ return false;
+ }
+}
\ No newline at end of file
diff --git a/src/utils/getWordCount.js b/src/utils/getWordCount.js
index 8deb835962..171ba82a9b 100644
--- a/src/utils/getWordCount.js
+++ b/src/utils/getWordCount.js
@@ -8,7 +8,8 @@ const wordCount = input
.filter(word => {
// Remove empty strings and standalone symbols
const cleanedWord = word.trim();
- return cleanedWord && !excludedSymbols.has(cleanedWord);
+ return cleanedWord && !excludedSymbols.has(cleanedWord) &&
+ !/^\d+$/.test(cleanedWord) // exclude if only digits;
}).length;
return wordCount;
diff --git a/src/utils/routePermissions.js b/src/utils/routePermissions.js
index a3c38f14fa..25eaddd49f 100644
--- a/src/utils/routePermissions.js
+++ b/src/utils/routePermissions.js
@@ -38,5 +38,6 @@ const RoutePermissions = {
faq: [''],
faqManagement: ['manageFAQs'],
accessHgnSkillsDashboard: ['accessHgnSkillsDashboard'],
+ createCollabJobAds: ['createCollabJobAds']
};
export default RoutePermissions;
diff --git a/yarn.lock b/yarn.lock
index 6064e0bcf3..1a9e97688e 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1197,28 +1197,6 @@
resolved "https://registry.npmjs.org/@dual-bundle/import-meta-resolve/-/import-meta-resolve-4.2.1.tgz"
integrity sha512-id+7YRUgoUX6CgV0DtuhirQWodeeA7Lf4i2x71JS/vtA5pRb/hIGWlw+G6MeXvsM+MXrz0VAydTGElX1rAfgPg==
-"@emnapi/core@^1.4.3":
- version "1.7.1"
- resolved "https://registry.npmjs.org/@emnapi/core/-/core-1.7.1.tgz"
- integrity sha512-o1uhUASyo921r2XtHYOHy7gdkGLge8ghBEQHMWmyJFoXlpU58kIrhhN3w26lpQb6dspetweapMn2CSNwQ8I4wg==
- dependencies:
- "@emnapi/wasi-threads" "1.1.0"
- tslib "^2.4.0"
-
-"@emnapi/runtime@^1.4.3":
- version "1.7.1"
- resolved "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.7.1.tgz"
- integrity sha512-PVtJr5CmLwYAU9PZDMITZoR5iAOShYREoR45EyyLrbntV50mdePTgUn4AmOw90Ifcj+x2kRjdzr1HP3RrNiHGA==
- dependencies:
- tslib "^2.4.0"
-
-"@emnapi/wasi-threads@1.1.0":
- version "1.1.0"
- resolved "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.1.0.tgz"
- integrity sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==
- dependencies:
- tslib "^2.4.0"
-
"@emotion/babel-plugin@^11.13.5":
version "11.13.5"
resolved "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.13.5.tgz"
@@ -1412,131 +1390,6 @@
"@ephox/katamari" "^9.1.6"
"@ephox/sand" "^6.0.10"
-"@esbuild/aix-ppc64@0.25.9":
- version "0.25.9"
- resolved "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.9.tgz"
- integrity sha512-OaGtL73Jck6pBKjNIe24BnFE6agGl+6KxDtTfHhy1HmhthfKouEcOhqpSL64K4/0WCtbKFLOdzD/44cJ4k9opA==
-
-"@esbuild/android-arm@0.25.9":
- version "0.25.9"
- resolved "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.9.tgz"
- integrity sha512-5WNI1DaMtxQ7t7B6xa572XMXpHAaI/9Hnhk8lcxF4zVN4xstUgTlvuGDorBguKEnZO70qwEcLpfifMLoxiPqHQ==
-
-"@esbuild/android-arm64@0.25.9":
- version "0.25.9"
- resolved "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.9.tgz"
- integrity sha512-IDrddSmpSv51ftWslJMvl3Q2ZT98fUSL2/rlUXuVqRXHCs5EUF1/f+jbjF5+NG9UffUDMCiTyh8iec7u8RlTLg==
-
-"@esbuild/android-x64@0.25.9":
- version "0.25.9"
- resolved "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.9.tgz"
- integrity sha512-I853iMZ1hWZdNllhVZKm34f4wErd4lMyeV7BLzEExGEIZYsOzqDWDf+y082izYUE8gtJnYHdeDpN/6tUdwvfiw==
-
-"@esbuild/darwin-arm64@0.25.9":
- version "0.25.9"
- resolved "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.9.tgz"
- integrity sha512-XIpIDMAjOELi/9PB30vEbVMs3GV1v2zkkPnuyRRURbhqjyzIINwj+nbQATh4H9GxUgH1kFsEyQMxwiLFKUS6Rg==
-
-"@esbuild/darwin-x64@0.25.9":
- version "0.25.9"
- resolved "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.9.tgz"
- integrity sha512-jhHfBzjYTA1IQu8VyrjCX4ApJDnH+ez+IYVEoJHeqJm9VhG9Dh2BYaJritkYK3vMaXrf7Ogr/0MQ8/MeIefsPQ==
-
-"@esbuild/freebsd-arm64@0.25.9":
- version "0.25.9"
- resolved "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.9.tgz"
- integrity sha512-z93DmbnY6fX9+KdD4Ue/H6sYs+bhFQJNCPZsi4XWJoYblUqT06MQUdBCpcSfuiN72AbqeBFu5LVQTjfXDE2A6Q==
-
-"@esbuild/freebsd-x64@0.25.9":
- version "0.25.9"
- resolved "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.9.tgz"
- integrity sha512-mrKX6H/vOyo5v71YfXWJxLVxgy1kyt1MQaD8wZJgJfG4gq4DpQGpgTB74e5yBeQdyMTbgxp0YtNj7NuHN0PoZg==
-
-"@esbuild/linux-arm@0.25.9":
- version "0.25.9"
- resolved "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.9.tgz"
- integrity sha512-HBU2Xv78SMgaydBmdor38lg8YDnFKSARg1Q6AT0/y2ezUAKiZvc211RDFHlEZRFNRVhcMamiToo7bDx3VEOYQw==
-
-"@esbuild/linux-arm64@0.25.9":
- version "0.25.9"
- resolved "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.9.tgz"
- integrity sha512-BlB7bIcLT3G26urh5Dmse7fiLmLXnRlopw4s8DalgZ8ef79Jj4aUcYbk90g8iCa2467HX8SAIidbL7gsqXHdRw==
-
-"@esbuild/linux-ia32@0.25.9":
- version "0.25.9"
- resolved "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.9.tgz"
- integrity sha512-e7S3MOJPZGp2QW6AK6+Ly81rC7oOSerQ+P8L0ta4FhVi+/j/v2yZzx5CqqDaWjtPFfYz21Vi1S0auHrap3Ma3A==
-
-"@esbuild/linux-loong64@0.25.9":
- version "0.25.9"
- resolved "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.9.tgz"
- integrity sha512-Sbe10Bnn0oUAB2AalYztvGcK+o6YFFA/9829PhOCUS9vkJElXGdphz0A3DbMdP8gmKkqPmPcMJmJOrI3VYB1JQ==
-
-"@esbuild/linux-mips64el@0.25.9":
- version "0.25.9"
- resolved "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.9.tgz"
- integrity sha512-YcM5br0mVyZw2jcQeLIkhWtKPeVfAerES5PvOzaDxVtIyZ2NUBZKNLjC5z3/fUlDgT6w89VsxP2qzNipOaaDyA==
-
-"@esbuild/linux-ppc64@0.25.9":
- version "0.25.9"
- resolved "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.9.tgz"
- integrity sha512-++0HQvasdo20JytyDpFvQtNrEsAgNG2CY1CLMwGXfFTKGBGQT3bOeLSYE2l1fYdvML5KUuwn9Z8L1EWe2tzs1w==
-
-"@esbuild/linux-riscv64@0.25.9":
- version "0.25.9"
- resolved "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.9.tgz"
- integrity sha512-uNIBa279Y3fkjV+2cUjx36xkx7eSjb8IvnL01eXUKXez/CBHNRw5ekCGMPM0BcmqBxBcdgUWuUXmVWwm4CH9kg==
-
-"@esbuild/linux-s390x@0.25.9":
- version "0.25.9"
- resolved "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.9.tgz"
- integrity sha512-Mfiphvp3MjC/lctb+7D287Xw1DGzqJPb/J2aHHcHxflUo+8tmN/6d4k6I2yFR7BVo5/g7x2Monq4+Yew0EHRIA==
-
-"@esbuild/linux-x64@0.25.9":
- version "0.25.9"
- resolved "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.9.tgz"
- integrity sha512-iSwByxzRe48YVkmpbgoxVzn76BXjlYFXC7NvLYq+b+kDjyyk30J0JY47DIn8z1MO3K0oSl9fZoRmZPQI4Hklzg==
-
-"@esbuild/netbsd-arm64@0.25.9":
- version "0.25.9"
- resolved "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.9.tgz"
- integrity sha512-9jNJl6FqaUG+COdQMjSCGW4QiMHH88xWbvZ+kRVblZsWrkXlABuGdFJ1E9L7HK+T0Yqd4akKNa/lO0+jDxQD4Q==
-
-"@esbuild/netbsd-x64@0.25.9":
- version "0.25.9"
- resolved "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.9.tgz"
- integrity sha512-RLLdkflmqRG8KanPGOU7Rpg829ZHu8nFy5Pqdi9U01VYtG9Y0zOG6Vr2z4/S+/3zIyOxiK6cCeYNWOFR9QP87g==
-
-"@esbuild/openbsd-arm64@0.25.9":
- version "0.25.9"
- resolved "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.9.tgz"
- integrity sha512-YaFBlPGeDasft5IIM+CQAhJAqS3St3nJzDEgsgFixcfZeyGPCd6eJBWzke5piZuZ7CtL656eOSYKk4Ls2C0FRQ==
-
-"@esbuild/openbsd-x64@0.25.9":
- version "0.25.9"
- resolved "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.9.tgz"
- integrity sha512-1MkgTCuvMGWuqVtAvkpkXFmtL8XhWy+j4jaSO2wxfJtilVCi0ZE37b8uOdMItIHz4I6z1bWWtEX4CJwcKYLcuA==
-
-"@esbuild/openharmony-arm64@0.25.9":
- version "0.25.9"
- resolved "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.9.tgz"
- integrity sha512-4Xd0xNiMVXKh6Fa7HEJQbrpP3m3DDn43jKxMjxLLRjWnRsfxjORYJlXPO4JNcXtOyfajXorRKY9NkOpTHptErg==
-
-"@esbuild/sunos-x64@0.25.9":
- version "0.25.9"
- resolved "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.9.tgz"
- integrity sha512-WjH4s6hzo00nNezhp3wFIAfmGZ8U7KtrJNlFMRKxiI9mxEK1scOMAaa9i4crUtu+tBr+0IN6JCuAcSBJZfnphw==
-
-"@esbuild/win32-arm64@0.25.9":
- version "0.25.9"
- resolved "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.9.tgz"
- integrity sha512-mGFrVJHmZiRqmP8xFOc6b84/7xa5y5YvR1x8djzXpJBSv/UsNK6aqec+6JDjConTgvvQefdGhFDAs2DLAds6gQ==
-
-"@esbuild/win32-ia32@0.25.9":
- version "0.25.9"
- resolved "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.9.tgz"
- integrity sha512-b33gLVU2k11nVx1OhX3C8QQP6UHQK4ZtN56oFWvVXvz2VkDoe6fbG8TOgHFxEvqeqohmRnIHe5A1+HADk4OQww==
-
"@esbuild/win32-x64@0.25.9":
version "0.25.9"
resolved "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.9.tgz"
@@ -2303,15 +2156,6 @@
reselect "^5.1.1"
use-sync-external-store "^1.5.0"
-"@napi-rs/wasm-runtime@^0.2.11":
- version "0.2.12"
- resolved "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.12.tgz"
- integrity sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==
- dependencies:
- "@emnapi/core" "^1.4.3"
- "@emnapi/runtime" "^1.4.3"
- "@tybys/wasm-util" "^0.10.0"
-
"@nicolo-ribaudo/eslint-scope-5-internals@5.1.1-v1":
version "5.1.1-v1"
resolved "https://registry.npmjs.org/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz"
@@ -2358,66 +2202,6 @@
resolved "https://registry.npmjs.org/@open-draft/until/-/until-2.1.0.tgz"
integrity sha512-U69T3ItWHvLwGg5eJ0n3I62nWuE6ilHlmz7zM0npLBRvPRd7e6NYmg54vvRtP5mZG7kZqZCFVdsTWo7BPtBujg==
-"@parcel/watcher-android-arm64@2.5.1":
- version "2.5.1"
- resolved "https://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.1.tgz"
- integrity sha512-KF8+j9nNbUN8vzOFDpRMsaKBHZ/mcjEjMToVMJOhTozkDonQFFrRcfdLWn6yWKCmJKmdVxSgHiYvTCef4/qcBA==
-
-"@parcel/watcher-darwin-arm64@2.5.1":
- version "2.5.1"
- resolved "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.1.tgz"
- integrity sha512-eAzPv5osDmZyBhou8PoF4i6RQXAfeKL9tjb3QzYuccXFMQU0ruIc/POh30ePnaOyD1UXdlKguHBmsTs53tVoPw==
-
-"@parcel/watcher-darwin-x64@2.5.1":
- version "2.5.1"
- resolved "https://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.1.tgz"
- integrity sha512-1ZXDthrnNmwv10A0/3AJNZ9JGlzrF82i3gNQcWOzd7nJ8aj+ILyW1MTxVk35Db0u91oD5Nlk9MBiujMlwmeXZg==
-
-"@parcel/watcher-freebsd-x64@2.5.1":
- version "2.5.1"
- resolved "https://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.1.tgz"
- integrity sha512-SI4eljM7Flp9yPuKi8W0ird8TI/JK6CSxju3NojVI6BjHsTyK7zxA9urjVjEKJ5MBYC+bLmMcbAWlZ+rFkLpJQ==
-
-"@parcel/watcher-linux-arm-glibc@2.5.1":
- version "2.5.1"
- resolved "https://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.1.tgz"
- integrity sha512-RCdZlEyTs8geyBkkcnPWvtXLY44BCeZKmGYRtSgtwwnHR4dxfHRG3gR99XdMEdQ7KeiDdasJwwvNSF5jKtDwdA==
-
-"@parcel/watcher-linux-arm-musl@2.5.1":
- version "2.5.1"
- resolved "https://registry.npmjs.org/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.1.tgz"
- integrity sha512-6E+m/Mm1t1yhB8X412stiKFG3XykmgdIOqhjWj+VL8oHkKABfu/gjFj8DvLrYVHSBNC+/u5PeNrujiSQ1zwd1Q==
-
-"@parcel/watcher-linux-arm64-glibc@2.5.1":
- version "2.5.1"
- resolved "https://registry.npmjs.org/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.1.tgz"
- integrity sha512-LrGp+f02yU3BN9A+DGuY3v3bmnFUggAITBGriZHUREfNEzZh/GO06FF5u2kx8x+GBEUYfyTGamol4j3m9ANe8w==
-
-"@parcel/watcher-linux-arm64-musl@2.5.1":
- version "2.5.1"
- resolved "https://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.1.tgz"
- integrity sha512-cFOjABi92pMYRXS7AcQv9/M1YuKRw8SZniCDw0ssQb/noPkRzA+HBDkwmyOJYp5wXcsTrhxO0zq1U11cK9jsFg==
-
-"@parcel/watcher-linux-x64-glibc@2.5.1":
- version "2.5.1"
- resolved "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.1.tgz"
- integrity sha512-GcESn8NZySmfwlTsIur+49yDqSny2IhPeZfXunQi48DMugKeZ7uy1FX83pO0X22sHntJ4Ub+9k34XQCX+oHt2A==
-
-"@parcel/watcher-linux-x64-musl@2.5.1":
- version "2.5.1"
- resolved "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.1.tgz"
- integrity sha512-n0E2EQbatQ3bXhcH2D1XIAANAcTZkQICBPVaxMeaCVBtOpBZpWJuf7LwyWPSBDITb7In8mqQgJ7gH8CILCURXg==
-
-"@parcel/watcher-win32-arm64@2.5.1":
- version "2.5.1"
- resolved "https://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.1.tgz"
- integrity sha512-RFzklRvmc3PkjKjry3hLF9wD7ppR4AKcWNzH7kXR7GUe0Igb3Nz8fyPwtZCSquGrhU5HhUNDr/mKBqj7tqA2Vw==
-
-"@parcel/watcher-win32-ia32@2.5.1":
- version "2.5.1"
- resolved "https://registry.npmjs.org/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.1.tgz"
- integrity sha512-c2KkcVN+NJmuA7CGlaGD1qJh1cLfDnQsHjE89E60vUEMlqduHGCdCLJCID5geFVM0dOtA3ZiIO8BoEQmzQVfpQ==
-
"@parcel/watcher-win32-x64@2.5.1":
version "2.5.1"
resolved "https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.1.tgz"
@@ -2582,101 +2366,6 @@
resolved "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.27.tgz"
integrity sha512-+d0F4MKMCbeVUJwG96uQ4SgAznZNSq93I3V+9NHA4OpvqG8mRCpGdKmK8l/dl02h2CCDHwW2FqilnTyDcAnqjA==
-"@rollup/rollup-android-arm-eabi@4.49.0":
- version "4.49.0"
- resolved "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.49.0.tgz"
- integrity sha512-rlKIeL854Ed0e09QGYFlmDNbka6I3EQFw7iZuugQjMb11KMpJCLPFL4ZPbMfaEhLADEL1yx0oujGkBQ7+qW3eA==
-
-"@rollup/rollup-android-arm64@4.49.0":
- version "4.49.0"
- resolved "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.49.0.tgz"
- integrity sha512-cqPpZdKUSQYRtLLr6R4X3sD4jCBO1zUmeo3qrWBCqYIeH8Q3KRL4F3V7XJ2Rm8/RJOQBZuqzQGWPjjvFUcYa/w==
-
-"@rollup/rollup-darwin-arm64@4.49.0":
- version "4.49.0"
- resolved "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.49.0.tgz"
- integrity sha512-99kMMSMQT7got6iYX3yyIiJfFndpojBmkHfTc1rIje8VbjhmqBXE+nb7ZZP3A5skLyujvT0eIUCUsxAe6NjWbw==
-
-"@rollup/rollup-darwin-x64@4.49.0":
- version "4.49.0"
- resolved "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.49.0.tgz"
- integrity sha512-y8cXoD3wdWUDpjOLMKLx6l+NFz3NlkWKcBCBfttUn+VGSfgsQ5o/yDUGtzE9HvsodkP0+16N0P4Ty1VuhtRUGg==
-
-"@rollup/rollup-freebsd-arm64@4.49.0":
- version "4.49.0"
- resolved "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.49.0.tgz"
- integrity sha512-3mY5Pr7qv4GS4ZvWoSP8zha8YoiqrU+e0ViPvB549jvliBbdNLrg2ywPGkgLC3cmvN8ya3za+Q2xVyT6z+vZqA==
-
-"@rollup/rollup-freebsd-x64@4.49.0":
- version "4.49.0"
- resolved "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.49.0.tgz"
- integrity sha512-C9KzzOAQU5gU4kG8DTk+tjdKjpWhVWd5uVkinCwwFub2m7cDYLOdtXoMrExfeBmeRy9kBQMkiyJ+HULyF1yj9w==
-
-"@rollup/rollup-linux-arm-gnueabihf@4.49.0":
- version "4.49.0"
- resolved "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.49.0.tgz"
- integrity sha512-OVSQgEZDVLnTbMq5NBs6xkmz3AADByCWI4RdKSFNlDsYXdFtlxS59J+w+LippJe8KcmeSSM3ba+GlsM9+WwC1w==
-
-"@rollup/rollup-linux-arm-musleabihf@4.49.0":
- version "4.49.0"
- resolved "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.49.0.tgz"
- integrity sha512-ZnfSFA7fDUHNa4P3VwAcfaBLakCbYaxCk0jUnS3dTou9P95kwoOLAMlT3WmEJDBCSrOEFFV0Y1HXiwfLYJuLlA==
-
-"@rollup/rollup-linux-arm64-gnu@4.49.0":
- version "4.49.0"
- resolved "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.49.0.tgz"
- integrity sha512-Z81u+gfrobVK2iV7GqZCBfEB1y6+I61AH466lNK+xy1jfqFLiQ9Qv716WUM5fxFrYxwC7ziVdZRU9qvGHkYIJg==
-
-"@rollup/rollup-linux-arm64-musl@4.49.0":
- version "4.49.0"
- resolved "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.49.0.tgz"
- integrity sha512-zoAwS0KCXSnTp9NH/h9aamBAIve0DXeYpll85shf9NJ0URjSTzzS+Z9evmolN+ICfD3v8skKUPyk2PO0uGdFqg==
-
-"@rollup/rollup-linux-loongarch64-gnu@4.49.0":
- version "4.49.0"
- resolved "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.49.0.tgz"
- integrity sha512-2QyUyQQ1ZtwZGiq0nvODL+vLJBtciItC3/5cYN8ncDQcv5avrt2MbKt1XU/vFAJlLta5KujqyHdYtdag4YEjYQ==
-
-"@rollup/rollup-linux-ppc64-gnu@4.49.0":
- version "4.49.0"
- resolved "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.49.0.tgz"
- integrity sha512-k9aEmOWt+mrMuD3skjVJSSxHckJp+SiFzFG+v8JLXbc/xi9hv2icSkR3U7uQzqy+/QbbYY7iNB9eDTwrELo14g==
-
-"@rollup/rollup-linux-riscv64-gnu@4.49.0":
- version "4.49.0"
- resolved "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.49.0.tgz"
- integrity sha512-rDKRFFIWJ/zJn6uk2IdYLc09Z7zkE5IFIOWqpuU0o6ZpHcdniAyWkwSUWE/Z25N/wNDmFHHMzin84qW7Wzkjsw==
-
-"@rollup/rollup-linux-riscv64-musl@4.49.0":
- version "4.49.0"
- resolved "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.49.0.tgz"
- integrity sha512-FkkhIY/hYFVnOzz1WeV3S9Bd1h0hda/gRqvZCMpHWDHdiIHn6pqsY3b5eSbvGccWHMQ1uUzgZTKS4oGpykf8Tw==
-
-"@rollup/rollup-linux-s390x-gnu@4.49.0":
- version "4.49.0"
- resolved "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.49.0.tgz"
- integrity sha512-gRf5c+A7QiOG3UwLyOOtyJMD31JJhMjBvpfhAitPAoqZFcOeK3Kc1Veg1z/trmt+2P6F/biT02fU19GGTS529A==
-
-"@rollup/rollup-linux-x64-gnu@4.49.0":
- version "4.49.0"
- resolved "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.49.0.tgz"
- integrity sha512-BR7+blScdLW1h/2hB/2oXM+dhTmpW3rQt1DeSiCP9mc2NMMkqVgjIN3DDsNpKmezffGC9R8XKVOLmBkRUcK/sA==
-
-"@rollup/rollup-linux-x64-musl@4.49.0":
- version "4.49.0"
- resolved "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.49.0.tgz"
- integrity sha512-hDMOAe+6nX3V5ei1I7Au3wcr9h3ktKzDvF2ne5ovX8RZiAHEtX1A5SNNk4zt1Qt77CmnbqT+upb/umzoPMWiPg==
-
-"@rollup/rollup-win32-arm64-msvc@4.49.0":
- version "4.49.0"
- resolved "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.49.0.tgz"
- integrity sha512-wkNRzfiIGaElC9kXUT+HLx17z7D0jl+9tGYRKwd8r7cUqTL7GYAvgUY++U2hK6Ar7z5Z6IRRoWC8kQxpmM7TDA==
-
-"@rollup/rollup-win32-ia32-msvc@4.49.0":
- version "4.49.0"
- resolved "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.49.0.tgz"
- integrity sha512-gq5aW/SyNpjp71AAzroH37DtINDcX1Qw2iv9Chyz49ZgdOP3NV8QCyKZUrGsYX9Yyggj5soFiRCgsL3HwD8TdA==
-
"@rollup/rollup-win32-x64-msvc@4.49.0":
version "4.49.0"
resolved "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.49.0.tgz"
@@ -2861,13 +2550,6 @@
dependencies:
prop-types "^15.6.2"
-"@tybys/wasm-util@^0.10.0":
- version "0.10.1"
- resolved "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.1.tgz"
- integrity sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==
- dependencies:
- tslib "^2.4.0"
-
"@types/aria-query@^4.2.0":
version "4.2.2"
resolved "https://registry.npmjs.org/@types/aria-query/-/aria-query-4.2.2.tgz"
@@ -3331,98 +3013,6 @@
resolved "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz"
integrity sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==
-"@unrs/resolver-binding-android-arm-eabi@1.11.1":
- version "1.11.1"
- resolved "https://registry.npmjs.org/@unrs/resolver-binding-android-arm-eabi/-/resolver-binding-android-arm-eabi-1.11.1.tgz"
- integrity sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw==
-
-"@unrs/resolver-binding-android-arm64@1.11.1":
- version "1.11.1"
- resolved "https://registry.npmjs.org/@unrs/resolver-binding-android-arm64/-/resolver-binding-android-arm64-1.11.1.tgz"
- integrity sha512-lCxkVtb4wp1v+EoN+HjIG9cIIzPkX5OtM03pQYkG+U5O/wL53LC4QbIeazgiKqluGeVEeBlZahHalCaBvU1a2g==
-
-"@unrs/resolver-binding-darwin-arm64@1.11.1":
- version "1.11.1"
- resolved "https://registry.npmjs.org/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.11.1.tgz"
- integrity sha512-gPVA1UjRu1Y/IsB/dQEsp2V1pm44Of6+LWvbLc9SDk1c2KhhDRDBUkQCYVWe6f26uJb3fOK8saWMgtX8IrMk3g==
-
-"@unrs/resolver-binding-darwin-x64@1.11.1":
- version "1.11.1"
- resolved "https://registry.npmjs.org/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.11.1.tgz"
- integrity sha512-cFzP7rWKd3lZaCsDze07QX1SC24lO8mPty9vdP+YVa3MGdVgPmFc59317b2ioXtgCMKGiCLxJ4HQs62oz6GfRQ==
-
-"@unrs/resolver-binding-freebsd-x64@1.11.1":
- version "1.11.1"
- resolved "https://registry.npmjs.org/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.11.1.tgz"
- integrity sha512-fqtGgak3zX4DCB6PFpsH5+Kmt/8CIi4Bry4rb1ho6Av2QHTREM+47y282Uqiu3ZRF5IQioJQ5qWRV6jduA+iGw==
-
-"@unrs/resolver-binding-linux-arm-gnueabihf@1.11.1":
- version "1.11.1"
- resolved "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.11.1.tgz"
- integrity sha512-u92mvlcYtp9MRKmP+ZvMmtPN34+/3lMHlyMj7wXJDeXxuM0Vgzz0+PPJNsro1m3IZPYChIkn944wW8TYgGKFHw==
-
-"@unrs/resolver-binding-linux-arm-musleabihf@1.11.1":
- version "1.11.1"
- resolved "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.11.1.tgz"
- integrity sha512-cINaoY2z7LVCrfHkIcmvj7osTOtm6VVT16b5oQdS4beibX2SYBwgYLmqhBjA1t51CarSaBuX5YNsWLjsqfW5Cw==
-
-"@unrs/resolver-binding-linux-arm64-gnu@1.11.1":
- version "1.11.1"
- resolved "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.11.1.tgz"
- integrity sha512-34gw7PjDGB9JgePJEmhEqBhWvCiiWCuXsL9hYphDF7crW7UgI05gyBAi6MF58uGcMOiOqSJ2ybEeCvHcq0BCmQ==
-
-"@unrs/resolver-binding-linux-arm64-musl@1.11.1":
- version "1.11.1"
- resolved "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.11.1.tgz"
- integrity sha512-RyMIx6Uf53hhOtJDIamSbTskA99sPHS96wxVE/bJtePJJtpdKGXO1wY90oRdXuYOGOTuqjT8ACccMc4K6QmT3w==
-
-"@unrs/resolver-binding-linux-ppc64-gnu@1.11.1":
- version "1.11.1"
- resolved "https://registry.npmjs.org/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.11.1.tgz"
- integrity sha512-D8Vae74A4/a+mZH0FbOkFJL9DSK2R6TFPC9M+jCWYia/q2einCubX10pecpDiTmkJVUH+y8K3BZClycD8nCShA==
-
-"@unrs/resolver-binding-linux-riscv64-gnu@1.11.1":
- version "1.11.1"
- resolved "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.11.1.tgz"
- integrity sha512-frxL4OrzOWVVsOc96+V3aqTIQl1O2TjgExV4EKgRY09AJ9leZpEg8Ak9phadbuX0BA4k8U5qtvMSQQGGmaJqcQ==
-
-"@unrs/resolver-binding-linux-riscv64-musl@1.11.1":
- version "1.11.1"
- resolved "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.11.1.tgz"
- integrity sha512-mJ5vuDaIZ+l/acv01sHoXfpnyrNKOk/3aDoEdLO/Xtn9HuZlDD6jKxHlkN8ZhWyLJsRBxfv9GYM2utQ1SChKew==
-
-"@unrs/resolver-binding-linux-s390x-gnu@1.11.1":
- version "1.11.1"
- resolved "https://registry.npmjs.org/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.11.1.tgz"
- integrity sha512-kELo8ebBVtb9sA7rMe1Cph4QHreByhaZ2QEADd9NzIQsYNQpt9UkM9iqr2lhGr5afh885d/cB5QeTXSbZHTYPg==
-
-"@unrs/resolver-binding-linux-x64-gnu@1.11.1":
- version "1.11.1"
- resolved "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.11.1.tgz"
- integrity sha512-C3ZAHugKgovV5YvAMsxhq0gtXuwESUKc5MhEtjBpLoHPLYM+iuwSj3lflFwK3DPm68660rZ7G8BMcwSro7hD5w==
-
-"@unrs/resolver-binding-linux-x64-musl@1.11.1":
- version "1.11.1"
- resolved "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.11.1.tgz"
- integrity sha512-rV0YSoyhK2nZ4vEswT/QwqzqQXw5I6CjoaYMOX0TqBlWhojUf8P94mvI7nuJTeaCkkds3QE4+zS8Ko+GdXuZtA==
-
-"@unrs/resolver-binding-wasm32-wasi@1.11.1":
- version "1.11.1"
- resolved "https://registry.npmjs.org/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.11.1.tgz"
- integrity sha512-5u4RkfxJm+Ng7IWgkzi3qrFOvLvQYnPBmjmZQ8+szTK/b31fQCnleNl1GgEt7nIsZRIf5PLhPwT0WM+q45x/UQ==
- dependencies:
- "@napi-rs/wasm-runtime" "^0.2.11"
-
-"@unrs/resolver-binding-win32-arm64-msvc@1.11.1":
- version "1.11.1"
- resolved "https://registry.npmjs.org/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.11.1.tgz"
- integrity sha512-nRcz5Il4ln0kMhfL8S3hLkxI85BXs3o8EYoattsJNdsX4YUU89iOkVn7g0VHSRxFuVMdM4Q1jEpIId1Ihim/Uw==
-
-"@unrs/resolver-binding-win32-ia32-msvc@1.11.1":
- version "1.11.1"
- resolved "https://registry.npmjs.org/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.11.1.tgz"
- integrity sha512-DCEI6t5i1NmAZp6pFonpD5m7i6aFrpofcp4LA2i8IIq60Jyo28hamKBxNrZcyOwVOZkgsRp9O2sXWBWP8MnvIQ==
-
"@unrs/resolver-binding-win32-x64-msvc@1.11.1":
version "1.11.1"
resolved "https://registry.npmjs.org/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.11.1.tgz"
@@ -6310,11 +5900,6 @@ fs.realpath@^1.0.0:
resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz"
integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==
-fsevents@^2.3.2, fsevents@^2.3.3, fsevents@~2.3.2, fsevents@~2.3.3:
- version "2.3.3"
- resolved "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz"
- integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==
-
function-bind@^1.1.2:
version "1.1.2"
resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz"
@@ -11058,7 +10643,7 @@ tsconfig-paths@^3.15.0:
minimist "^1.2.6"
strip-bom "^3.0.0"
-tslib@^2.0.0, tslib@^2.4.0:
+tslib@^2.0.0:
version "2.8.1"
resolved "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz"
integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==