| @@ -25,8 +25,9 @@ import { | |||
| // STATS_PAGE, | |||
| REGISTER_PAGE, | |||
| // CREATE_AD_PAGE, | |||
| FILES_PAGE, | |||
| FILES_VIEW_PAGE, | |||
| ADD_FILE, | |||
| FILES_PAGE, | |||
| } from "./constants/pages"; | |||
| import LoginPage from "./pages/LoginPage/LoginPageMUI"; | |||
| @@ -50,8 +51,9 @@ import UserDetails from "./pages/UsersPage/UserDetails"; | |||
| // import StatsPage from "./pages/StatsPage/StatsPage"; | |||
| import RegisterPage from "./pages/RegisterPage/RegisterPage"; | |||
| // import CreateAdPage from "./pages/AdsPage/CreateAdPage"; | |||
| import FilesPage from "./pages/FilesPage/FilesPage"; | |||
| import FilesViewPage from "./pages/FilesPage/FilesViewPage"; | |||
| import AddFile from "./pages/FilesPage/AddFile"; | |||
| import FilesPage from "./pages/FilesPage/FilesPage"; | |||
| const AppRoutes = () => { | |||
| const dispatch = useDispatch(); | |||
| @@ -83,8 +85,10 @@ const AppRoutes = () => { | |||
| <PrivateRoute exact path={USERS_PAGE} component={UsersPage} /> | |||
| {/* <PrivateRoute exact path={CANDIDATES_PAGE} component={CandidatesPage} /> | |||
| <PrivateRoute exact path={CREATE_AD_PAGE} component={CreateAdPage} /> */} | |||
| <PrivateRoute exact path={FILES_PAGE} component={FilesPage} /> | |||
| {/* <PrivateRoute exact path={FILES_PAGE} component={FilesPage} /> */} | |||
| <PrivateRoute exact path={FILES_VIEW_PAGE} component={FilesViewPage} /> | |||
| <PrivateRoute exact path={ADD_FILE} component={AddFile}/> | |||
| <PrivateRoute exact path={FILES_PAGE} component={FilesPage}/> | |||
| {/* <PrivateRoute | |||
| exact | |||
| path={CANDIDATES_DETAILS_PAGE} | |||
| @@ -38,8 +38,7 @@ import en from "../../assets/images/en.png"; | |||
| const NavbarComponent = () => { | |||
| const navItems = [ | |||
| "users", | |||
| "filesView", | |||
| // "signOut" | |||
| "files" | |||
| ]; | |||
| const { pathname } = useLocation(); | |||
| const [openDrawer, setOpenDrawer] = useState(false); | |||
| @@ -21,4 +21,5 @@ export const STATS_PAGE = '/statistics'; | |||
| export const REGISTER_PAGE = '/register'; | |||
| export const CREATE_AD_PAGE = '/create-ad'; | |||
| export const FILES_PAGE = '/files'; | |||
| export const FILES_VIEW_PAGE = '/filesView'; | |||
| export const FILES_VIEW_PAGE = '/files-view'; | |||
| export const ADD_FILE = '/add-file'; | |||
| @@ -130,8 +130,7 @@ export default { | |||
| users: "Users", | |||
| signOut: "Sign Out", | |||
| schedule:"Schedule", | |||
| files:"Files", | |||
| filesView:"Files View", | |||
| files:"Files" | |||
| }, | |||
| ads: { | |||
| activeAds: "Active Ads", | |||
| @@ -147,9 +147,8 @@ export default { | |||
| patterns: "Šabloni", | |||
| statistics: "Statistika", | |||
| users: "Korisnici", | |||
| files:"Fajlovi", | |||
| signOut: "Izloguj se", | |||
| filesView:"Pregled fajlova", | |||
| files:"Fajlovi" | |||
| }, | |||
| ads: { | |||
| activeAds: "Aktivni Oglasi", | |||
| @@ -0,0 +1,233 @@ | |||
| import React, { useState } from "react"; | |||
| import { Checkbox, FormControlLabel, MenuItem, Select } from "@mui/material"; | |||
| import { useTranslation } from "react-i18next"; | |||
| import uploadIcon from "../../assets/images/upload.png"; | |||
| import IconButton from "../../components/IconButton/IconButton"; | |||
| import { useSelector, useDispatch } from "react-redux"; | |||
| import { selectCategories } from "../../store/selectors/categoriesSelector"; | |||
| import { useEffect } from "react"; | |||
| import { setCategoriesReq } from "../../store/actions/categories/categoriesAction"; | |||
| import { | |||
| changeTagIsCheckedValue, | |||
| resetIsCheckedTagsValue, | |||
| setTagsReq, | |||
| } from "../../store/actions/tags/tagsAction"; | |||
| import { selectTags } from "../../store/selectors/tagsSelector"; | |||
| import { uploadFileReq } from "../../store/actions/uploadFile/uploadFileActions"; | |||
| import { FILES_VIEW_PAGE } from "../../constants/pages"; | |||
| import PropTypes from "prop-types"; | |||
| const AddFile = ({history}) => { | |||
| const [dropzoneActive, setDropzoneActive] = useState(false); | |||
| const [pdfFile, setPdfFile] = useState(null); | |||
| const [title, setTitle] = useState(""); | |||
| const dispatch = useDispatch(); | |||
| const categories = useSelector(selectCategories); | |||
| const tags = useSelector(selectTags); | |||
| const [selectedCategory, setSelectedCategory] = useState(null); | |||
| const { t } = useTranslation(); | |||
| useEffect(() => { | |||
| dispatch(setCategoriesReq()); | |||
| dispatch(setTagsReq()); | |||
| }, []); | |||
| const onSuccessUploadFile = () => { | |||
| dispatch(resetIsCheckedTagsValue()); | |||
| setPdfFile(null); | |||
| setTitle("") | |||
| }; | |||
| const handleDrop = (e) => { | |||
| e.preventDefault(); | |||
| const selectedFile = e.dataTransfer.files[0]; | |||
| setPdfFile(selectedFile); | |||
| }; | |||
| const handleChangeInputFile = (e) => { | |||
| const selectedFile = e.target.files[0]; | |||
| setPdfFile(selectedFile); | |||
| }; | |||
| const selectCategoryHandler = (e) => { | |||
| setSelectedCategory(e.target.value); | |||
| }; | |||
| const onChangeTagsCheckbox = (id) => { | |||
| dispatch(changeTagIsCheckedValue(id)); | |||
| }; | |||
| const uploadFileHandler = () => { | |||
| const tagsIds = tags | |||
| .filter((tag) => tag.isChecked === true) | |||
| .map((tag) => Number(tag.id)); | |||
| dispatch( | |||
| uploadFileReq({ | |||
| title, | |||
| categoryId: selectedCategory, | |||
| tagsIds, | |||
| fileToUpload: pdfFile, | |||
| onSuccessUploadFile, | |||
| }) | |||
| ); | |||
| }; | |||
| return ( | |||
| <div className="files-page"> | |||
| <div className="files-page-card"> | |||
| <div className="files-page-card-title"> | |||
| <h1>Title</h1> | |||
| </div> | |||
| <div className="files-page-card-content"> | |||
| <input | |||
| type="text" | |||
| className="create-ad-form-control-first-step-input" | |||
| onChange={(e) => setTitle(e.target.value)} | |||
| value={title} | |||
| placeholder="Document Title" | |||
| /> | |||
| </div> | |||
| </div> | |||
| <div className="files-page-card"> | |||
| <div className="files-page-card-title"> | |||
| <h1>Categories</h1> | |||
| </div> | |||
| <div className="files-page-card-content"> | |||
| <Select | |||
| labelId="files-page-card-content-select" | |||
| id="files-page-card-content-selectt" | |||
| sx={{ width: "100%", borderColor: "#e4e4e4 !important" }} | |||
| onChange={selectCategoryHandler} | |||
| value={selectedCategory} | |||
| > | |||
| {categories && | |||
| categories.map((category, index) => ( | |||
| <MenuItem | |||
| key={index} | |||
| sx={{ textAlign: "left" }} | |||
| value={category.id} | |||
| > | |||
| {category.name} | |||
| </MenuItem> | |||
| ))} | |||
| </Select> | |||
| </div> | |||
| </div> | |||
| <div className="files-page-card"> | |||
| <div className="files-page-card-title"> | |||
| <h1>Tags</h1> | |||
| </div> | |||
| <div className="files-page-card-content"> | |||
| <div className="files-page-card-content-checkboxes"> | |||
| {tags && | |||
| tags.map((tag) => ( | |||
| <FormControlLabel | |||
| key={tag.id} | |||
| control={ | |||
| <Checkbox | |||
| value={tag.name} | |||
| checked={tag.isChecked} | |||
| onChange={onChangeTagsCheckbox.bind(this, tag.id)} | |||
| className="create-ad-second-step-checkbox" | |||
| /> | |||
| } | |||
| label={tag.name} | |||
| /> | |||
| ))} | |||
| </div> | |||
| </div> | |||
| </div> | |||
| <div className="files-page-card"> | |||
| <div className="files-page-card-title"> | |||
| <h1>Drag & Drop File</h1> | |||
| </div> | |||
| <div className="files-page-card-content"> | |||
| <div | |||
| className="uploadCV-input files-page-drag-and-drop" | |||
| onDragOver={(e) => { | |||
| setDropzoneActive(true); | |||
| e.preventDefault(); | |||
| }} | |||
| onDragLeave={(e) => { | |||
| setDropzoneActive(false); | |||
| e.preventDefault(); | |||
| }} | |||
| onDrop={(e) => handleDrop(e)} | |||
| style={{ | |||
| backgroundColor: dropzoneActive ? "#F4F4F4" : "#ffffff", | |||
| }} | |||
| > | |||
| <div className="uploadCV-input-sub-container"> | |||
| <img src={uploadIcon} /> | |||
| <div className="uploadCV-input-sub-container"> | |||
| {pdfFile !== null ? ( | |||
| <p>{pdfFile.name}</p> | |||
| ) : ( | |||
| <> | |||
| <p> | |||
| {t("ads.dragPdf1")} | |||
| <label | |||
| htmlFor="upload-file" | |||
| style={{ | |||
| cursor: "pointer", | |||
| textDecoration: "underline", | |||
| color: "#1E92D0", | |||
| }} | |||
| > | |||
| {t("common.search")} | |||
| </label> | |||
| {t("ads.dragPdf2")} | |||
| </p> | |||
| <input | |||
| type="file" | |||
| name="photo" | |||
| id="upload-file" | |||
| style={{ display: "none", zIndex: -1 }} | |||
| value={pdfFile} | |||
| data-testid="apply-for-ad-modal-fourth-stage-pdf-input" | |||
| // accept=".pdf" | |||
| onChange={handleChangeInputFile} | |||
| /> | |||
| </> | |||
| )} | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| <div className="files-page-card"> | |||
| <div className="files-page-card-add-button" style={{alignItems:'center'}}> | |||
| <p | |||
| className="applicant-ads-back-button" | |||
| onClick={() => history.push(FILES_VIEW_PAGE)} | |||
| > | |||
| Nazad na sve fajlove | |||
| </p> | |||
| <IconButton | |||
| className="c-btn ads-page-btn c-btn--primary add-ad-btn" | |||
| onClick={uploadFileHandler} | |||
| > | |||
| + {t("files.addFile")} | |||
| </IconButton> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| ); | |||
| }; | |||
| AddFile.propTypes = { | |||
| history: PropTypes.shape({ | |||
| replace: PropTypes.func, | |||
| push: PropTypes.func, | |||
| location: PropTypes.shape({ | |||
| pathname: PropTypes.string, | |||
| }), | |||
| }), | |||
| }; | |||
| export default AddFile; | |||
| @@ -1,233 +1,21 @@ | |||
| import React, { useState } from "react"; | |||
| import { Checkbox, FormControlLabel, MenuItem, Select } from "@mui/material"; | |||
| import { useTranslation } from "react-i18next"; | |||
| import uploadIcon from "../../assets/images/upload.png"; | |||
| import IconButton from "../../components/IconButton/IconButton"; | |||
| import { useSelector, useDispatch } from "react-redux"; | |||
| import { selectCategories } from "../../store/selectors/categoriesSelector"; | |||
| import { useEffect } from "react"; | |||
| import React, { useEffect } from 'react' | |||
| import { setCategoriesReq } from "../../store/actions/categories/categoriesAction"; | |||
| import { | |||
| changeTagIsCheckedValue, | |||
| resetIsCheckedTagsValue, | |||
| setTagsReq, | |||
| } from "../../store/actions/tags/tagsAction"; | |||
| import { selectTags } from "../../store/selectors/tagsSelector"; | |||
| import { uploadFileReq } from "../../store/actions/uploadFile/uploadFileActions"; | |||
| import { FILES_VIEW_PAGE } from "../../constants/pages"; | |||
| import PropTypes from "prop-types"; | |||
| import { selectCategories } from "../../store/selectors/categoriesSelector"; | |||
| import { useDispatch, useSelector } from 'react-redux'; | |||
| const FilesPage = ({history}) => { | |||
| const [dropzoneActive, setDropzoneActive] = useState(false); | |||
| const [pdfFile, setPdfFile] = useState(null); | |||
| const [title, setTitle] = useState(""); | |||
| const dispatch = useDispatch(); | |||
| const FilesPage = () => { | |||
| const dispatch = useDispatch() | |||
| const categories = useSelector(selectCategories); | |||
| const tags = useSelector(selectTags); | |||
| const [selectedCategory, setSelectedCategory] = useState(null); | |||
| const { t } = useTranslation(); | |||
| useEffect(() => { | |||
| dispatch(setCategoriesReq()); | |||
| dispatch(setTagsReq()); | |||
| }, []); | |||
| const onSuccessUploadFile = () => { | |||
| dispatch(resetIsCheckedTagsValue()); | |||
| setPdfFile(null); | |||
| setTitle("") | |||
| }; | |||
| const handleDrop = (e) => { | |||
| e.preventDefault(); | |||
| const selectedFile = e.dataTransfer.files[0]; | |||
| setPdfFile(selectedFile); | |||
| }; | |||
| const handleChangeInputFile = (e) => { | |||
| const selectedFile = e.target.files[0]; | |||
| setPdfFile(selectedFile); | |||
| }; | |||
| const selectCategoryHandler = (e) => { | |||
| setSelectedCategory(e.target.value); | |||
| }; | |||
| const onChangeTagsCheckbox = (id) => { | |||
| dispatch(changeTagIsCheckedValue(id)); | |||
| }; | |||
| const uploadFileHandler = () => { | |||
| const tagsIds = tags | |||
| .filter((tag) => tag.isChecked === true) | |||
| .map((tag) => Number(tag.id)); | |||
| dispatch( | |||
| uploadFileReq({ | |||
| title, | |||
| categoryId: selectedCategory, | |||
| tagsIds, | |||
| fileToUpload: pdfFile, | |||
| onSuccessUploadFile, | |||
| }) | |||
| ); | |||
| }; | |||
| }) | |||
| return ( | |||
| <div className="files-page"> | |||
| <div className="files-page-card"> | |||
| <div className="files-page-card-title"> | |||
| <h1>Title</h1> | |||
| </div> | |||
| <div className="files-page-card-content"> | |||
| <input | |||
| type="text" | |||
| className="create-ad-form-control-first-step-input" | |||
| onChange={(e) => setTitle(e.target.value)} | |||
| value={title} | |||
| placeholder="Document Title" | |||
| /> | |||
| </div> | |||
| </div> | |||
| <div className="files-page-card"> | |||
| <div className="files-page-card-title"> | |||
| <h1>Categories</h1> | |||
| </div> | |||
| <div className="files-page-card-content"> | |||
| <Select | |||
| labelId="files-page-card-content-select" | |||
| id="files-page-card-content-selectt" | |||
| sx={{ width: "100%", borderColor: "#e4e4e4 !important" }} | |||
| onChange={selectCategoryHandler} | |||
| value={selectedCategory} | |||
| > | |||
| {categories && | |||
| categories.map((category, index) => ( | |||
| <MenuItem | |||
| key={index} | |||
| sx={{ textAlign: "left" }} | |||
| value={category.id} | |||
| > | |||
| {category.name} | |||
| </MenuItem> | |||
| ))} | |||
| </Select> | |||
| </div> | |||
| </div> | |||
| <div className="files-page-card"> | |||
| <div className="files-page-card-title"> | |||
| <h1>Tags</h1> | |||
| </div> | |||
| <div className="files-page-card-content"> | |||
| <div className="files-page-card-content-checkboxes"> | |||
| {tags && | |||
| tags.map((tag) => ( | |||
| <FormControlLabel | |||
| key={tag.id} | |||
| control={ | |||
| <Checkbox | |||
| value={tag.name} | |||
| checked={tag.isChecked} | |||
| onChange={onChangeTagsCheckbox.bind(this, tag.id)} | |||
| className="create-ad-second-step-checkbox" | |||
| /> | |||
| } | |||
| label={tag.name} | |||
| /> | |||
| ))} | |||
| </div> | |||
| </div> | |||
| </div> | |||
| <div className="files-page-card"> | |||
| <div className="files-page-card-title"> | |||
| <h1>Drag & Drop File</h1> | |||
| </div> | |||
| <div className="files-page-card-content"> | |||
| <div | |||
| className="uploadCV-input files-page-drag-and-drop" | |||
| onDragOver={(e) => { | |||
| setDropzoneActive(true); | |||
| e.preventDefault(); | |||
| }} | |||
| onDragLeave={(e) => { | |||
| setDropzoneActive(false); | |||
| e.preventDefault(); | |||
| }} | |||
| onDrop={(e) => handleDrop(e)} | |||
| style={{ | |||
| backgroundColor: dropzoneActive ? "#F4F4F4" : "#ffffff", | |||
| }} | |||
| > | |||
| <div className="uploadCV-input-sub-container"> | |||
| <img src={uploadIcon} /> | |||
| <div className="uploadCV-input-sub-container"> | |||
| {pdfFile !== null ? ( | |||
| <p>{pdfFile.name}</p> | |||
| ) : ( | |||
| <> | |||
| <p> | |||
| {t("ads.dragPdf1")} | |||
| <label | |||
| htmlFor="upload-file" | |||
| style={{ | |||
| cursor: "pointer", | |||
| textDecoration: "underline", | |||
| color: "#1E92D0", | |||
| }} | |||
| > | |||
| {t("common.search")} | |||
| </label> | |||
| {t("ads.dragPdf2")} | |||
| </p> | |||
| <input | |||
| type="file" | |||
| name="photo" | |||
| id="upload-file" | |||
| style={{ display: "none", zIndex: -1 }} | |||
| value={pdfFile} | |||
| data-testid="apply-for-ad-modal-fourth-stage-pdf-input" | |||
| // accept=".pdf" | |||
| onChange={handleChangeInputFile} | |||
| /> | |||
| </> | |||
| )} | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| <div className="files-page-card"> | |||
| <div className="files-page-card-add-button" style={{alignItems:'center'}}> | |||
| <p | |||
| className="applicant-ads-back-button" | |||
| onClick={() => history.push(FILES_VIEW_PAGE)} | |||
| > | |||
| Nazad na sve fajlove | |||
| </p> | |||
| <IconButton | |||
| className="c-btn ads-page-btn c-btn--primary add-ad-btn" | |||
| onClick={uploadFileHandler} | |||
| > | |||
| + {t("files.addFile")} | |||
| </IconButton> | |||
| </div> | |||
| </div> | |||
| <div> | |||
| {categories.map((category,index) => ( | |||
| <p key={index}>{category.name}</p> | |||
| )) } | |||
| </div> | |||
| ); | |||
| }; | |||
| FilesPage.propTypes = { | |||
| history: PropTypes.shape({ | |||
| replace: PropTypes.func, | |||
| push: PropTypes.func, | |||
| location: PropTypes.shape({ | |||
| pathname: PropTypes.string, | |||
| }), | |||
| }), | |||
| }; | |||
| ) | |||
| } | |||
| export default FilesPage; | |||
| export default FilesPage | |||
| @@ -17,7 +17,7 @@ import Fade from "@mui/material/Fade"; | |||
| import { useTranslation } from "react-i18next"; | |||
| import searchImage from "../../assets/images/search.png"; | |||
| import IconButton from "../../components/IconButton/IconButton"; | |||
| import { FILES_PAGE } from "../../constants/pages"; | |||
| import { ADD_FILE } from "../../constants/pages"; | |||
| import PropTypes from "prop-types"; | |||
| const FilesViewPage = ({history}) => { | |||
| @@ -281,7 +281,7 @@ const FilesViewPage = ({history}) => { | |||
| /> | |||
| <IconButton | |||
| className="c-btn ads-page-btn c-btn--primary add-ad-btn filesPage" | |||
| onClick={() => history.push(FILES_PAGE)} | |||
| onClick={() => history.push(ADD_FILE)} | |||
| > | |||
| + Fajl | |||
| </IconButton> | |||
| @@ -16,7 +16,7 @@ import { | |||
| fetchGoogleUser, | |||
| } from "../../store/actions/login/loginActions"; | |||
| import { selectLoginError } from "../../store/selectors/loginSelectors"; | |||
| import { FORGOT_PASSWORD_PAGE,FILES_VIEW_PAGE } from "../../constants/pages"; | |||
| import { FORGOT_PASSWORD_PAGE,FILES_VIEW_PAGE, FILES_PAGE } from "../../constants/pages"; | |||
| import { | |||
| Box, | |||
| Button, | |||
| @@ -83,8 +83,7 @@ const LoginPage = ({ history }) => { | |||
| const handleApiResponseSuccess = () => { | |||
| history.push({ | |||
| pathname: FILES_VIEW_PAGE, | |||
| pathname: FILES_VIEW_PAGE, | |||
| pathname: FILES_PAGE, | |||
| state: { | |||
| from: history.location.pathname, | |||
| }, | |||