Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Validate company application page #309

Open
wants to merge 19 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
280f5bf
Added validation of company application route and unverified state
FranciscoCardoso913 Feb 4, 2023
6284d08
Implemented validation page design
FranciscoCardoso913 Feb 6, 2023
aa0ac75
Added appropriate error messages for application
FranciscoCardoso913 Feb 11, 2023
a246730
Changed hyperlinks and redirect to Link component and changed text to…
FranciscoCardoso913 May 9, 2023
80cfaf3
Solved redirected to home page issue and refactored validation page code
FranciscoCardoso913 Jun 20, 2023
b328a12
Added a waring to MyOffers page and to the CreateOffer page when comp…
FranciscoCardoso913 Jun 20, 2023
502ae8f
Added a waring to MyOffers page and to the CreateOffer page when comp…
FranciscoCardoso913 Jun 20, 2023
61dafc3
Merge remote-tracking branch 'origin/validate-company-application-Pag…
FranciscoCardoso913 Jun 20, 2023
df27afe
Conditionally render the alert for non yet approved companies and cha…
dsantosferreira Jun 27, 2023
02072ab
Rewriting the website messages to match the current flow
FranciscoCardoso913 Jul 4, 2023
52dbd3f
Rewriting the website messages to match the current flow
FranciscoCardoso913 Jul 4, 2023
a327f00
Fixing failing tests
FranciscoCardoso913 Aug 8, 2023
4c33b8d
Created test to check if approve and reject buttons are not rendered …
dsantosferreira Aug 18, 2023
3a5a721
Tests for validation page
FranciscoCardoso913 Aug 19, 2023
4f85e5f
Tests for validation page
FranciscoCardoso913 Aug 19, 2023
95794d0
Tests for the alerts components in the company offer management page …
FranciscoCardoso913 Aug 19, 2023
4198681
Making tests for the validate application and the fetch company appli…
FranciscoCardoso913 Aug 29, 2023
decd155
Add extra error message to validation page, fixed: can enter create o…
FranciscoCardoso913 Sep 16, 2023
23032fa
Merge branch 'develop' into validate-company-application-Page
FranciscoCardoso913 Sep 16, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .env
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ HOST_PORT=443
REACT_APP_API_HOSTNAME="https://localhost:8087"

# Uncomment to disable devtools
# REACT_APP_ALLOW_DEV_TOOLS=false
#REACT_APP_ALLOW_DEV_TOOLS=false

# Google Analytics' Universal ID
ANALYTICS_ID=
Expand Down
10 changes: 10 additions & 0 deletions src/AppRouter.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import EditOfferPage from "./pages/EditOfferPage";
import PrivacyPolicyPage from "./pages/PrivacyPolicyPage";
import TermsAndConditionsPage from "./pages/TermsAndConditionsPage";
import ChangeLogPage from "./pages/ChangeLogPage";
import ValidationPage from "./pages/ValidationPage";

/**
*
Expand Down Expand Up @@ -135,6 +136,15 @@ const AppRouter = () => (
<RulesPage />
</PageLayout>
</Route>
<Route exact path="/apply/:token/validate" key="/apply/:token/validate">
<PageLayout
key="/apply/:token/validate"
pageTitle="Validate Company Application"
layout={LayoutType.DESKTOP}
>
<ValidationPage />
</PageLayout>
</Route>
<ProtectedRoute
exact
key="/review/applications"
Expand Down
7 changes: 4 additions & 3 deletions src/components/Apply/Company/ApplicationConfirmation.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import Constants from "../../../utils/Constants";

const useStyles = makeStyles((theme) => ({
content: {
textAlgin: "justify",
textAlign: "justify",
},
actions: {
margin: theme.spacing(1),
Expand All @@ -22,14 +22,15 @@ const ApplicationConfirmation = () => {
<CardHeader title="Application Submitted" />
<CardContent className={classes.content}>
<Typography variant="body2">
Application Submitted, you should receive a confirmation email shortly. If not, please contact us:
Application Submitted: You should receive an email containing a confirmation link for your application.
Please confirm it within 10 minutes; otherwise, the link will expire. If you have not received an email, please contact us at
{" "}
<Link color="secondary" href={`mailto:${Constants.CONTACT_US_EMAIL}`}>
{Constants.CONTACT_US_EMAIL}
</Link>
</Typography>
<Typography variant="body2" className={classes.secondText}>
{"Once you're approved, you will receive an email, and then you can log into NIJobs! "}
{"Once your application is approved, you will receive an email. Then, you can log into NIJobs. "}
Do not forget your password, you will need it on the first login.
</Typography>
</CardContent>
Expand Down
30 changes: 28 additions & 2 deletions src/components/Apply/Company/CompanyApplicationUtils.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import { validationRulesGenerator, generalHumanError } from "../../../utils";
import { AuthConstants } from "../../Navbar/Auth/AuthUtils";


export const CompanyApplicationConstants = {
password: AuthConstants.password,
motivation: {
Expand All @@ -19,6 +17,34 @@ export const generateValidationRule = validationRulesGenerator(CompanyApplicatio
const HumanReadableErrors = Object.freeze({
"email-already-exists": "The provided email is already associated to our platform.",
"company-application-duplicate-email": "There is already an application associated with that email.",
"company-application-recently-created": "There is an application created less than 10 minutes ago associated with this email.",
});

const ValidationErrors = Object.freeze({
"invalid-token": {
title: "Error! Application does not exist!",
text: "An error has occurred while validating your application! The application you are trying to validate does not exist.",
},
"expired-token": {
title: "Error! Link has expired!",
text: "An error has occurred while validating your application. The link that was sent to you has expired." +
" You will need to create a new application.",
},
"application-already-validated": {
title: "Application is already validated!",
text: "This application is already validated. ",
FranciscoCardoso913 marked this conversation as resolved.
Show resolved Hide resolved
},
});

export const getValidationError = (error) => {
const errorMsg = { title: "Unexpected Error!", text: "An unexpected error has occurred while validating your application. " };
if (!error) {
return errorMsg;
}
if (typeof ValidationErrors[error] === "object") {
return ValidationErrors[error];
}
return errorMsg;
};

export const getHumanError = (error) => generalHumanError(error, HumanReadableErrors);
36 changes: 32 additions & 4 deletions src/components/Offers/Form/form-components/OfferForm.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ import {
FormControl,
Typography,
Collapse,
Button,
Button, makeStyles,
} from "@material-ui/core";
import React, { useState, useCallback, useContext } from "react";
import React, {useState, useCallback, useContext, useEffect} from "react";
import { Redirect } from "react-router-dom";
import PropTypes from "prop-types";
import MultiOptionTextField from "../../../utils/form/MultiOptionTextField";
Expand All @@ -36,13 +36,18 @@ import { Controller } from "react-hook-form";
import { useMobile } from "../../../../utils/media-queries";
import "../editor.css";
import ApplyURLComponent from "./ApplyURLComponent";
import { Alert } from "../../../utils/Alert";
import { fetchCompanyApplicationState } from "../../../../services/companyService";
import useSession from "../../../../hooks/useSession.js";
import { addSnackbar } from "../../../../actions/notificationActions";

export const PAID_OPTIONS = [
{ value: "none", label: "Unspecified" },
{ value: true, label: "Paid" },
{ value: false, label: "Unpaid" },
];


const OfferForm = ({ context, title }) => {
const {
submit,
Expand Down Expand Up @@ -92,6 +97,27 @@ const OfferForm = ({ context, title }) => {
const Content = isMobile ? DialogContent : CardContent;
const classes = useOfferFormStyles(isMobile)();

const [state, setState] = useState( "APPROVED");
const session = useSession();

useEffect(() => {
if(!session.isValidating && session.isLoggedIn) {
const request = fetchCompanyApplicationState(session.data?.company?._id)
.then((state) => {
setState(state);
})
.catch(() => {
addSnackbar({
message: "An unexpected error occurred, please try refreshing the browser window.",
key: `${Date.now()}-fetchCompanyApplicationsError`,
});
});
return () => {
request.cancel();
};
}
}, [addSnackbar, session.isValidating, session.isLoggedIn]);

const showOwnerComponent = isAdmin && showCompanyField;

const SelectStylingProps = {
Expand All @@ -107,7 +133,9 @@ const OfferForm = ({ context, title }) => {
? <Redirect to={`/offer/${offerId}`} push />
:
<div className={classes.formCard}>
<CardHeader title={!isMobile && title } />
{(state !== "APPROVED") && session.isLoggedIn && <Alert type={"warning"}
fontSize={1.2}>{"This offer will stay hidden from the public until your account is approved!"}</Alert>}
<CardHeader title={!isMobile && title}/>
<Content className={classes.formContent}>
<ConnectedLoginAlert
isLoggedIn={isLoggedIn}
Expand Down Expand Up @@ -164,7 +192,7 @@ const OfferForm = ({ context, title }) => {
<Controller
name="fields"
render={(
{ field: { onBlur, name } },
{ field: { onBlur, name } },
) => (
<MultiOptionAutocomplete
name={name}
Expand Down
9 changes: 9 additions & 0 deletions src/components/Offers/Form/form-components/offerStyles.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,4 +73,13 @@ export default (isMobile) => makeStyles((theme) => ({
paddingTop: theme.spacing(2),
marginTop: theme.spacing(2),
},
warning:{
fontSize:"1.2em",
"& .MuiAlert-icon": {
fontSize: "1.5em"
},
marginBottom:"1em"


},
}));
1 change: 0 additions & 1 deletion src/components/Offers/New/CreateOfferForm.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

import React, { useCallback } from "react";
import { parseRequestErrors } from "../Form/OfferUtils";
import { newOffer } from "../../../services/offerService";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ export const columns = {
};

export const ApplicationStateLabel = Object.freeze({
UNVERIFIED: "Unverified",
dsantosferreira marked this conversation as resolved.
Show resolved Hide resolved
APPROVED: "Approved",
PENDING: "Pending",
REJECTED: "Rejected",

});
33 changes: 33 additions & 0 deletions src/components/utils/Alert.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import {Alert as MUI_Alert, AlertTitle} from "@material-ui/lab";
import {makeStyles} from "@material-ui/core";
import PropTypes from "prop-types";
import { Warning as WarningIcon } from "@material-ui/icons";
import React from 'react';

const useStyles = (props) => makeStyles((theme) => ({

content:{
fontSize: props.fontSize+"em",
"& .MuiAlert-icon": {
fontSize: (props.fontSize+0.3)+"em"
},
margin:"0.5em 0em"
},
}));

export const Alert = ({type, title, fontSize = 1, children}) => {
const classes = useStyles({fontSize: fontSize})();
return (
<MUI_Alert severity={type} className={classes.content} icon={<WarningIcon />}>
{title ? <AlertTitle>{title}</AlertTitle> : null}
{children}
</MUI_Alert>
)
}

Alert.propTypes = {
type: PropTypes.oneOf(["error", "warning", "info", "success"]),
title: PropTypes.string,
children: PropTypes.string,
fontSize: PropTypes.number,
}
36 changes: 34 additions & 2 deletions src/pages/CompanyOffersManagementPage.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,53 @@
import React from "react";
import React, {useEffect, useState} from "react";
import CompanyOffersManagementWidget from "../components/Company/Offers/Manage/CompanyOffersManagementWidget";
import { CardContent, makeStyles } from "@material-ui/core";
import { useMobile } from "../utils/media-queries";
import { Alert } from "../components/utils/Alert";
import { fetchCompanyApplicationState } from "../services/companyService";
import useSession from "../hooks/useSession";
import { addSnackbar } from "../actions/notificationActions";

const useStyles = (isMobile) => makeStyles((theme) => ({
content: {
padding: isMobile ? theme.spacing(2, 2) : theme.spacing(3, 9),
},

}));

const CompanyOffersManagementPage = () => {
const isMobile = useMobile();
const classes = useStyles(isMobile)();
const [state, setState_] = useState( "APPROVED");
const session = useSession();

useEffect(() => {
if(!session.isValidating && session.isLoggedIn) {
const request = fetchCompanyApplicationState(session.data?.company?._id)
.then((state_) => {
console.log(state_);
console.log("Tipo");
console.log(typeof state_);
setState_(state_);
console.log(state);

})
.catch(() => {
addSnackbar({
message: "An unexpected error occurred, please try refreshing the browser window.",
key: `${Date.now()}-fetchCompanyApplicationsError`,
});
});
return () => {
request.cancel();
};
}
}, [addSnackbar, session.isLoggedIn, session.isValidating]);

return (
<CardContent className={classes.content}>
<CompanyOffersManagementWidget isMobile={isMobile} />
{(state !== "APPROVED") && session.isLoggedIn && <Alert type={"warning"}
fontSize={1.2}>{"Your offers will stay hidden from the public until your account is approved!"}</Alert>}
<CompanyOffersManagementWidget isMobile={isMobile}/>
</CardContent>
);
};
Expand Down
1 change: 1 addition & 0 deletions src/pages/CreateOfferPage.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React from "react";
import CreateOfferForm from "../components/Offers/New/CreateOfferForm";
import {Alert} from "@material-ui/lab";

const CreateOfferPage = () => (
<>
Expand Down
Loading