Browse Source

First commit

newRequest
Nikola Ignjatovic 4 years ago
parent
commit
cbf47c194c

+ 15
- 14
src/App.js View File

@@ -4,23 +4,24 @@ import { Helmet } from 'react-helmet-async';
import i18next from 'i18next';
import history from './store/utils/history';
import Header from './components/Header/Header';
import Sidebar from './components/Sidebar/Sidebar';
// import Sidebar from './components/Sidebar/Sidebar';
import AppRoutes from './AppRoutes';

const App = () => (
<div className="wrapper">
<Router history={history}>
<Helmet>
<title>
{i18next.t('app.title')}
</title>
</Helmet>
<>
<Header />
<Sidebar />
</>
</Router>

</div>
<Router history={history}>
<Helmet>
<title>
{i18next.t('app.title')}
</title>
</Helmet>
<>
<Header />
{/* <Sidebar /> */}
<AppRoutes />
</>
</Router>

);

export default App;

+ 24
- 18
src/AppRoutes.js View File

@@ -2,35 +2,41 @@ import React from 'react';
import { Redirect, Route, Switch } from 'react-router-dom';

import {
LOGIN_PAGE,
//LOGIN_PAGE,
HOME_PAGE,
FORGOT_PASSWORD_PAGE,
//FORGOT_PASSWORD_PAGE,
SCRAPE_RESULTS_PAGE,
NOT_FOUND_PAGE,
ERROR_PAGE,
BASE_PAGE,
} from './constants/pages';

import LoginPage from './pages/LoginPage/LoginPage';
//import LoginPage from './pages/LoginPage/LoginPage';
import HomePage from './pages/HomePage/HomePage';
import ScrapeResultsPage from './pages/ScrapeResults/ScrapeResultsPage';
import NotFoundPage from './pages/ErrorPages/NotFoundPage';
import ErrorPage from './pages/ErrorPages/ErrorPage';
import ForgotPasswordPage from './pages/ForgotPasswordPage/ForgotPasswordPage';
import PrivateRoute from './components/Router/PrivateRoute';
//import ForgotPasswordPage from './pages/ForgotPasswordPage/ForgotPasswordPage';
//import PrivateRoute from './components/Router/PrivateRoute';

const AppRoutes = () => (
<Switch>
<Route exact path={BASE_PAGE} component={LoginPage} />
<Route exact path={LOGIN_PAGE} component={LoginPage} />
<Route path={NOT_FOUND_PAGE} component={NotFoundPage} />
<Route path={ERROR_PAGE} component={ErrorPage} />
<Route path={FORGOT_PASSWORD_PAGE} component={ForgotPasswordPage} />
<PrivateRoute
exact
path={HOME_PAGE}
component={HomePage}
/>
<Redirect from="*" to={NOT_FOUND_PAGE} />
</Switch>
<div className="container content">
<Switch>
<Route exact path={BASE_PAGE} component={HomePage} />
<Route exact path={HOME_PAGE} component={HomePage} />
<Route exact path={SCRAPE_RESULTS_PAGE} component={ScrapeResultsPage} />
{/* <Route exact path={LOGIN_PAGE} component={LoginPage} /> */}
<Route path={NOT_FOUND_PAGE} component={NotFoundPage} />
<Route path={ERROR_PAGE} component={ErrorPage} />
{/* <Route path={FORGOT_PASSWORD_PAGE} component={ForgotPasswordPage} /> */}
{/* <PrivateRoute
exact
path={HOME_PAGE}
component={HomePage}
/> */}
<Redirect from="*" to={NOT_FOUND_PAGE} />
</Switch>
</div>
);



+ 11
- 0
src/assets/styles/_custom.scss View File

@@ -0,0 +1,11 @@
.content{
margin-top: 70px;
}
.btn-outline-primary
{
height:38px;
}
.cursor-pointer
{
cursor: pointer;
}

+ 81
- 0
src/components/CreateScrapeRequest/CreateScrapeRequest.js View File

@@ -0,0 +1,81 @@
import React, {useState} from 'react';
import { useTranslation } from 'react-i18next';
import Select from 'react-select'
import { prices, beds, types, lifeStyles } from '../../constants/filters';
import './CreateScrapeRequest.scss'

const CreateScrapeRequest = () => {

const { t } = useTranslation();
const [inputLocation, setLocation] = useState('')
const [priceFilter, setPriceFilter] = useState('')
const [bedFilter, setBedFilter] = useState('')
const [typeFilter, setTypeFilter] = useState('')
const [lifeStyleFilter, setLifeStyleFilter] = useState('')
const handleChangePriceType = async selectedOption => {
setPriceFilter(selectedOption)
};
const handleChangeBedType = async selectedOption => {
setBedFilter(selectedOption)
};
const handleChangeFilterType = async selectedOption => {
setTypeFilter(selectedOption)
};

const handleChangeLifeStyleType = async selectedOption => {
setLifeStyleFilter(selectedOption)
};

function handleSubmit (event){
event.preventDefault()
console.log(inputLocation);
console.log(priceFilter);
console.log(bedFilter);
console.log(typeFilter);
console.log(lifeStyleFilter);
}
return (
<div className="card card-primary">
<div className="card-header">
<h3 className="card-title">{t('createScrapeRequest.Title')}</h3>
</div>
<form >
<div className="card-body">
<div className="row">
<div className="col-md-3">
<div className="form-group">
<input type="text" className="form-control input-field cursor-pointer" value={inputLocation} placeholder={t('createScrapeRequest.LocationPlaceholder')} onChange={e => setLocation(e.target.value)}/>
</div>
</div>
<div className="col-md-2">
<div className="form-group">
<Select options={prices} onChange={handleChangePriceType} />
</div>
</div>
<div className="col-md-2">
<div className="form-group">
<Select className="cursor-pointer" options={beds} onChange={handleChangeBedType}/>
</div>
</div>
<div className="col-md-2">
<Select className="cursor-pointer" options={types} onChange={handleChangeFilterType}/>
</div>
<div className="col-md-2">
<Select className="cursor-pointer" options={lifeStyles} onChange={handleChangeLifeStyleType}/>
</div>
<div className="col-md-1">
<button type="submit" onClick={handleSubmit} className="btn btn-outline-primary cursor-pointer">Request</button>
</div>
</div>
</div>
</form>
</div>
);
};

CreateScrapeRequest.propTypes = {};

export default CreateScrapeRequest;

+ 3
- 0
src/components/CreateScrapeRequest/CreateScrapeRequest.scss View File

@@ -0,0 +1,3 @@
.input-field{
height:38px;
}

+ 14
- 110
src/components/Header/Header.js View File

@@ -1,116 +1,20 @@
import React from 'react';

import {Link} from 'react-router-dom';
import './Header.scss';
const Header = () => {


return (
<nav className="main-header navbar navbar-expand navbar-white navbar-light">
<ul className="navbar-nav">
<li className="nav-item">
<a className="nav-link" data-widget="pushmenu" href="#"><i className="fas fa-bars" /></a>
</li>
<li className="nav-item d-none d-sm-inline-block">
<a href="index3.html" className="nav-link">Home</a>
</li>
<li className="nav-item d-none d-sm-inline-block">
<a href="#" className="nav-link">Contact</a>
</li>
</ul>
<form className="form-inline ml-3">
<div className="input-group input-group-sm">
<input className="form-control form-control-navbar" type="search" placeholder="Search" aria-label="Search" />
<div className="input-group-append">
<button className="btn btn-navbar" type="submit">
<i className="fas fa-search" />
</button>
return (
<nav className="navbar navbar-expand-md navbar-light navbar-white">
<div className="container">
<Link to="/" className="navbar-brand">
<img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRmiNXzLyS4xRsUFmpTynL40UuAaOtMrnHtpw&usqp=CAU" alt="Scrapper" className="brand-image img-circle elevation-3" />
<span className="brand-text font-weight-light">Scrapper</span>
</Link>
<button className="navbar-toggler order-1" type="button" data-toggle="collapse" data-target="#navbarCollapse" aria-controls="navbarCollapse" aria-expanded="false" aria-label="Toggle navigation">
<span className="navbar-toggler-icon"></span>
</button>
</div>
</div>
</form>
<ul className="navbar-nav ml-auto">
<li className="nav-item dropdown">
<a className="nav-link" data-toggle="dropdown" href="#">
<i className="far fa-comments" />
<span className="badge badge-danger navbar-badge">3</span>
</a>
<div className="dropdown-menu dropdown-menu-lg dropdown-menu-right">
<a href="#" className="dropdown-item">
<div className="media">
<img src="dist/img/user1-128x128.jpg" alt="User Avatar" className="img-size-50 mr-3 img-circle" />
<div className="media-body">
<h3 className="dropdown-item-title">
<span className="float-right text-sm text-danger"><i className="fas fa-star" /></span>
</h3>
<p className="text-sm">Call me whenever you can...</p>
<p className="text-sm text-muted"><i className="far fa-clock mr-1" /> 4 Hours Ago</p>
</div>
</div>
</a>
<div className="dropdown-divider" />
<a href="#" className="dropdown-item">
<div className="media">
<img src="dist/img/user8-128x128.jpg" alt="User Avatar" className="img-size-50 img-circle mr-3" />
<div className="media-body">
<h3 className="dropdown-item-title">
John Pierce
<span className="float-right text-sm text-muted"><i className="fas fa-star" /></span>
</h3>
<p className="text-sm">I got your message bro</p>
<p className="text-sm text-muted"><i className="far fa-clock mr-1" /> 4 Hours Ago</p>
</div>
</div>
</a>
<div className="dropdown-divider" />
<a href="#" className="dropdown-item">
<div className="media">
<img src="dist/img/user3-128x128.jpg" alt="User Avatar" className="img-size-50 img-circle mr-3" />
<div className="media-body">
<h3 className="dropdown-item-title">
Nora Silvester
<span className="float-right text-sm text-warning"><i className="fas fa-star" /></span>
</h3>
<p className="text-sm">The subject goes here</p>
<p className="text-sm text-muted"><i className="far fa-clock mr-1" /> 4 Hours Ago</p>
</div>
</div>
</a>
<div className="dropdown-divider" />
<a href="#" className="dropdown-item dropdown-footer">See All Messages</a>
</div>
</li>
<li className="nav-item dropdown">
<a className="nav-link" data-toggle="dropdown" href="#">
<i className="far fa-bell" />
<span className="badge badge-warning navbar-badge">15</span>
</a>
<div className="dropdown-menu dropdown-menu-lg dropdown-menu-right">
<span className="dropdown-item dropdown-header">15 Notifications</span>
<div className="dropdown-divider" />
<a href="#" className="dropdown-item">
<i className="fas fa-envelope mr-2" /> 4 new messages
<span className="float-right text-muted text-sm">3 mins</span>
</a>
<div className="dropdown-divider" />
<a href="#" className="dropdown-item">
<i className="fas fa-users mr-2" /> 8 friend requests
<span className="float-right text-muted text-sm">12 hours</span>
</a>
<div className="dropdown-divider" />
<a href="#" className="dropdown-item">
<i className="fas fa-file mr-2" /> 3 new reports
<span className="float-right text-muted text-sm">2 days</span>
</a>
<div className="dropdown-divider" />
<a href="#" className="dropdown-item dropdown-footer">See All Notifications</a>
</div>
</li>
<li className="nav-item">
<a className="nav-link" data-widget="control-sidebar" data-slide="true" href="#">
<i className="fas fa-th-large" />
</a>
</li>
</ul>
</nav>

</nav>
);
};


+ 3
- 0
src/components/Header/Header.scss View File

@@ -0,0 +1,3 @@
.brand-image {
height:33px;
}

+ 39
- 0
src/components/ScrapeRequest/ScrapeRequest.js View File

@@ -0,0 +1,39 @@
import React from 'react';
import { useTranslation } from 'react-i18next';

const ScrapeRequest = (scrape) => {

const { t } = useTranslation();

function handleSubmit(event)
{
event.preventDefault();

}
return (
<tr>
<td>
<p>
</p><h3>{scrape.Title}</h3>
<span className="text-muted">Count {scrape.Count} +</span>
<span> | </span>
<span className="text-muted">{t('scrapeRequest.EstimatedTime')} {scrape.EstimatedTime}</span>
<span> | </span>
{t('scrapeRequest.ViewScrape')} <a href="scrappe.html"> {scrape.Url}</a>
<p></p>
<p>
</p>
</td>
<td>
{/* {scrape.Filters.map(element => (
<span key={element.id} className="badge bg-primary">{element.type}</span>
))} */}
</td>
<td><button type="submit" className="btn btn-xs btn-block btn-primary" onClick={handleSubmit}><i className="fa fa-bell"></i>{t('common.execute')}</button>
</td>
</tr>
);
}

export default ScrapeRequest;

+ 95
- 0
src/components/ScrapeRequests/ScrapeRequests.js View File

@@ -0,0 +1,95 @@
import React from 'react';
import { useTranslation } from 'react-i18next';
import ScrapeRequest from '../ScrapeRequest/ScrapeRequest';

const ScrapeRequests = () => {

const { t } = useTranslation();
const scrape = { Title : "#1 Chicago, IL", Count : "200", EstimatedTime : "20/7/2021 20:30AM", Url : "https://www.apartments.com/chicago-il/", Filters : [ {id: 1, type:"prices"}, {id:2, type : "beds"}, {id:3, type : "type"}, {id:4, type:"lifestyle"}] };
return (
<div className="card">
<div className="card-header">
<h3 className="card-title">{t('scrapeRequests.Title')}</h3>
</div>
<div classNameName="card-body p-0">
<table className="table table-sm">
<thead>
<tr>
<th>{t('scrapeRequests.Columns.Scrape')}</th>
<th>{t('scrapeRequests.Columns.Filters')}</th>
<th>{t('scrapeRequests.Columns.Status')}</th>
</tr>
</thead>
<tbody>
<ScrapeRequest scrape = {scrape} />
{/* <tr>
<td>
<p>
</p><h3> </h3>
<span className="text-muted">Count 200+</span>
<span> | </span>
<span className="text-muted">Estimated time 20/7/2021 20:30AM</span>
<span> | </span>
view scrape origin <a href="scrappe.html">https://www.apartments.com/chicago-il/</a>
<p></p>
<p>
</p>
</td>
<td>
<span className="badge bg-primary">price</span>
<span className="badge bg-primary">beds</span>
<span className="badge bg-primary">type</span>
<span className="badge bg-primary">lifestyle</span>
</td>
<td><button className="btn btn-xs btn-block btn-primary"><i className="fa fa-bell"></i>Execute</button>
</td>
</tr>
<tr>
<td>
<h3>#2 New York, NY </h3>
<span className="text-muted">Count 200+</span>
<span> | </span>
<span className="text-muted">Estimated time 20/7/2021 20:30AM</span>
<span> | </span>
view scrape origin <a href="scrappe.html">https://www.apartments.com/chicago-il/</a>
</td>
<td>
<span className="badge bg-primary">price</span>
<span className="badge bg-primary">beds</span>
<span className="badge bg-primary">type</span>
<span className="badge bg-primary">lifestyle</span>
</td>
<td><span className="badge bg-warning">Pending</span></td>
</tr>
<tr>
<td>
<h3>#3 New York, NY </h3>
<span className="text-muted">Count 200+</span>
<span> | </span>
<span className="text-muted">Estimated time 20/7/2021 20:30AM</span>
<span> | </span>
view scrape origin <a href="scrappe.html">https://www.apartments.com/chicago-il/</a>
</td>
<td>
<span className="badge bg-primary">price</span>
<span className="badge bg-primary">beds</span>
<span className="badge bg-primary">type</span>
<span className="badge bg-primary">lifestyle</span>
</td>
<td><span className="badge bg-success">Done</span></td>
</tr>
*/}
</tbody>
</table>
</div>
</div>
);

}

export default ScrapeRequests;

+ 29
- 0
src/constants/filters.js View File

@@ -0,0 +1,29 @@
export const prices = [
{ value: '$1000', label: '$1000' },
{ value: '$1100', label: '$1100' },
{ value: '$1300', label: '$1300' },
{ value: '$1500', label: '$1500' },
{ value: '$1800', label: '$1800' },
{ value: '$2000', label: '$2000' }
];
export const beds = [
{ value: '1', label: '1' },
{ value: '2', label: '2' },
{ value: '3', label: '3' },
{ value: '4+', label: '4+' }
];

export const types = [
{ value: 'apartments', label: 'apartments' },
{ value: 'houses', label: 'houses' },
{ value: 'condos', label: 'condos' },
{ value: 'townhomes', label: 'townhomes' },
];
export const lifeStyles = [
{ value: 'student-housing', label: 'Student' },
{ value: 'senior-housing', label: 'Senior Housing' },
{ value: 'short-term', label: 'Short Term' },
{ value: 'military', label: 'Military Housing'},
{value:'corporate' , label: 'Corporate Housing'}
];

+ 2
- 1
src/constants/pages.js View File

@@ -3,4 +3,5 @@ export const LOGIN_PAGE = '/login';
export const FORGOT_PASSWORD_PAGE = '/forgot-password';
export const HOME_PAGE = '/home';
export const ERROR_PAGE = '/error-page';
export const NOT_FOUND_PAGE = '/not-found';
export const NOT_FOUND_PAGE = '/not-found';
export const SCRAPE_RESULTS_PAGE = '/scrape-results';

+ 4
- 0
src/helpers/CreateUrl.js View File

@@ -0,0 +1,4 @@
export function CreateUrl(){

return '';
}

+ 18
- 0
src/i18n/resources/en.js View File

@@ -26,6 +26,7 @@ export default {
remove: 'Remove',
invite: 'Invite',
save: 'Save',
execute:'Execute',
complete: 'Complete',
download: 'Download',
yes: 'Yes',
@@ -83,5 +84,22 @@ export default {
},
apiErrors:{
ClientIpAddressIsNullOrEmpty:"Client Ip address is null or empty"
},
createScrapeRequest: {
Title: "Request new scrappe",
LocationPlaceholder : "Location or Point of Interest"
},
scrapeRequests: {
Title: "Scrappes",
Columns: {
Scrape:"Scrappe",
Filters:"Filters",
Status:"Status"
}
},
scrapeRequest:{
EstimatedTime: "Estimated time:",
ViewScrape:"view scrape origin"
}

};

+ 1
- 0
src/main.scss View File

@@ -20,3 +20,4 @@
@import './assets/styles/layout';
@import './assets/styles/overwrite';
@import './assets/styles/utility';
@import './assets/styles/custom';

+ 9
- 5
src/pages/HomePage/HomePage.js View File

@@ -1,12 +1,16 @@
import React from 'react';
import { Link } from 'react-router-dom';
import CreateScrapeRequest from '../../components/CreateScrapeRequest/CreateScrapeRequest';
import ScrapeRequests from '../../components/ScrapeRequests/ScrapeRequests';

const HomePage = () => {

return (
<div className="c-error-page">
<div className="c-error-page__content">
<h1 className="c-error-page__title">Home page</h1>
</div>
</div>
<>
<CreateScrapeRequest />
<ScrapeRequests />
<Link to='/scrape-results' >See results</Link>
</>
);
};


+ 0
- 0
src/pages/HomePage/Homepage.scss View File


+ 1
- 1
src/pages/LoginPage/LoginPage.js View File

@@ -3,7 +3,7 @@ import PropTypes from 'prop-types';

const LoginPage = () => {

return (
<aside className="main-sidebar">
<section className="sidebar">

+ 15
- 0
src/pages/ScrapeResults/ScrapeResultsPage.js View File

@@ -0,0 +1,15 @@
import React from 'react';

const ScrapeResultsPage = () => {
return (
<div className="c-error-page">
<div className="c-error-page__content">
Scrape results page
</div>
</div>
);
};

ScrapeResultsPage.propTypes = {};

export default ScrapeResultsPage;

+ 2
- 0
src/store/saga/scraperSaga.js View File

@@ -0,0 +1,2 @@
import { all, call, put, takeLatest } from '@redux-saga/core/effects';


Loading…
Cancel
Save