Просмотр исходного кода

Scraper details

scraperSetails
Nikola Ignjatovic 4 лет назад
Родитель
Сommit
1f534270a0

+ 23
- 0
package-lock.json Просмотреть файл

} }
} }
}, },
"classnames": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.1.tgz",
"integrity": "sha512-OlQdbZ7gLfGarSqxesMesDa5uz7KFbID8Kpq/SxIoNGDqY8lSYs0D+hhtBXhcdB3rcbXArFr7vlHheLk1voeNA=="
},
"clean-css": { "clean-css": {
"version": "4.2.3", "version": "4.2.3",
"resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.3.tgz", "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.3.tgz",
"scheduler": "^0.20.2" "scheduler": "^0.20.2"
} }
}, },
"react-easy-swipe": {
"version": "0.0.21",
"resolved": "https://registry.npmjs.org/react-easy-swipe/-/react-easy-swipe-0.0.21.tgz",
"integrity": "sha512-OeR2jAxdoqUMHIn/nS9fgreI5hSpgGoL5ezdal4+oO7YSSgJR8ga+PkYGJrSrJ9MKlPcQjMQXnketrD7WNmNsg==",
"requires": {
"prop-types": "^15.5.8"
}
},
"react-error-overlay": { "react-error-overlay": {
"version": "6.0.9", "version": "6.0.9",
"resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.9.tgz", "resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.9.tgz",
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.8.3.tgz", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.8.3.tgz",
"integrity": "sha512-X8jZHc7nCMjaCqoU+V2I0cOhNW+QMBwSUkeXnTi8IPe6zaRWfn60ZzvFDZqWPfmSJfjub7dDW1SP0jaHWLu/hg==" "integrity": "sha512-X8jZHc7nCMjaCqoU+V2I0cOhNW+QMBwSUkeXnTi8IPe6zaRWfn60ZzvFDZqWPfmSJfjub7dDW1SP0jaHWLu/hg=="
}, },
"react-responsive-carousel": {
"version": "3.2.19",
"resolved": "https://registry.npmjs.org/react-responsive-carousel/-/react-responsive-carousel-3.2.19.tgz",
"integrity": "sha512-lOO6CscsxnQoNnrmLXNXu7u3U0znY44jGloX9Zayki9+OdUs63YXypSgV7dzaTmlem4SXy4rIXBR8+gjA9zyxg==",
"requires": {
"classnames": "^2.2.5",
"prop-types": "^15.5.8",
"react-easy-swipe": "^0.0.21"
}
},
"react-router": { "react-router": {
"version": "5.2.0", "version": "5.2.0",
"resolved": "https://registry.npmjs.org/react-router/-/react-router-5.2.0.tgz", "resolved": "https://registry.npmjs.org/react-router/-/react-router-5.2.0.tgz",

+ 1
- 0
package.json Просмотреть файл

"react-helmet-async": "^1.0.9", "react-helmet-async": "^1.0.9",
"react-i18next": "^11.10.0", "react-i18next": "^11.10.0",
"react-redux": "^7.2.4", "react-redux": "^7.2.4",
"react-responsive-carousel": "^3.2.19",
"react-router-dom": "^5.2.0", "react-router-dom": "^5.2.0",
"react-scripts": "4.0.3", "react-scripts": "4.0.3",
"react-select": "^4.3.1", "react-select": "^4.3.1",

+ 3
- 2
src/App.js Просмотреть файл

import { Helmet } from 'react-helmet-async'; import { Helmet } from 'react-helmet-async';
import i18next from 'i18next'; import i18next from 'i18next';
import history from './store/utils/history'; import history from './store/utils/history';
import Header from './components/Header/Header';
//import Header from './components/Header/Header';
import "react-responsive-carousel/lib/styles/carousel.min.css";
// import Sidebar from './components/Sidebar/Sidebar'; // import Sidebar from './components/Sidebar/Sidebar';
import AppRoutes from './AppRoutes'; import AppRoutes from './AppRoutes';


</title> </title>
</Helmet> </Helmet>
<> <>
<Header />
{/* <Header /> */}
{/* <Sidebar /> */} {/* <Sidebar /> */}
<AppRoutes /> <AppRoutes />
</> </>

+ 7
- 0
src/assets/styles/_custom.scss Просмотреть файл

.cursor-pointer .cursor-pointer
{ {
cursor: pointer; cursor: pointer;
}
a{
color: #007bff!important;
cursor: pointer;
}
h1{
font-size: 80px!important;
} }

+ 130
- 0
src/components/CardApartments/CardApartments.js Просмотреть файл

import React from 'react';
import PropTypes from 'prop-types';
import getHours from '../../helpers/GetTodaysWorkingHours';
import './CardApartments.scss';

const CardApartments = ({result, index}) => {
const carouselId = "carouselExampleIndicators".concat(index);
const carouselIndicator = "#".concat(carouselId);
return(
<>
<div className="card">
<div className="card-body">
{result.lastUpdate !=undefined ?
<div className="ribbon-wrapper ribbon-lg">
<div className="ribbon bg-primary">
{result.lastUpdate}
</div>
</div> :''
}
<div className="row">
<div className="col-md-4">
<div id={carouselId} className="carousel slide" data-ride="carousel">
<ol className="carousel-indicators">
{result.images.map((image, i) =>
(image !== undefined && image.src !==undefined ?
i === 1 ?
<li data-target={carouselIndicator} data-slide-to={i} className="active"></li>
:
<li data-target={carouselIndicator} data-slide-to={i} className=""></li>
:""
))}
</ol>
<div className="carousel-inner">
{
result.images.map((image, i) =>
(image !== undefined && image.src !== undefined ?
i === 0 ?
<div className="carousel-item active" key={i} >
<img height="269px" className="d-block w-100"
src={image.src}
alt= {i} />
</div>
:
<div className="carousel-item" key={i} >
<img height="269px" className="d-block w-100"
src={image.src}
alt= {i} />
</div>
:'')
)
}
</div>
<a className="carousel-control-prev" href={carouselIndicator} role="button"
data-slide="prev">
<span className="carousel-control-custom-icon" aria-hidden="true">
<i className="fas fa-chevron-left"></i>
</span>
<span className="sr-only">Previous</span>
</a>
<a className="carousel-control-next" href={carouselIndicator} role="button"
data-slide="next">
<span className="carousel-control-custom-icon" aria-hidden="true">
<i className="fas fa-chevron-right"></i>
</span>
<span className="sr-only">Next</span>
</a>
</div>
</div>
<div className="col-md-8">
{result.name !== undefined ? <h2><a>{result.name}

</a>
{result.contact != undefined && result.contact.officeHours && getHours(result.contact.officeHours) !== null ? <span className="text-black-50 text-sm"><i className="fas fa-clock"></i> Open { getHours(result.contact.officeHours)} Today</span>: '' }
</h2>: ''}
{result.address != undefined ?
<p className="lead">
{result.address.street !== undefined ? <span> {result.address.street}, </span>:''}
{result.address.city !== undefined ? <span> {result.address.city}, </span>:''}
{result.address.zip !== undefined ? <span> {result.address.zip.code} {result.address.zip.state}</span>:''}
</p>
: ''}
{result.rentInfo !=undefined ? <h3 className="strong">{result.rentInfo}</h3>:'' }
<p className="card-text mb-1">
{result.description !== undefined ? result.description.substr(0,100) + "..." : ''}
</p>
<div className="row">
<div className="col-md-8">
<div className="row">
<div className="col">
{
result.features.map((feature, i) => <p key={i} className="badge badge-primary">{feature}</p>)
}
</div>
</div>
<div className="row">
{ result.contact !== undefined && result.contact.phone != undefined ? <span className="mr-3 lead"><i className="fas fa-phone">{result.contact.phone}</i></span> : ''}
{ result.contact !== undefined && result.contact.url !== undefined ? <span className="mr-3 lead"><a href={result.contact.url}><i className="fas fa-external-link-square-alt"></i> View property site</a></span>: '' }
</div>
</div>
<div className="col-md-3">
<div className="info-box mb-0">
<span className="info-box-icon bg-danger"><i className="far fa-star"></i></span>
{result.review != undefined ?
<div className="info-box-content">
<span className="info-box-text">Review</span>
<span className="info-box-number">{result.review} stars</span>
</div>
:''}
</div>
</div>
</div>

</div>
</div>
</div>
</div>
</>
);
}

CardApartments.propTypes = {
result: PropTypes.object,
index : PropTypes.string
}
export default CardApartments;

+ 4
- 0
src/components/CardApartments/CardApartments.scss Просмотреть файл

.image-height
{
height: 269px;
}

+ 122
- 0
src/components/CardCondos/CardCondos.js Просмотреть файл

import React from 'react';
import PropTypes from 'prop-types';

const CardCondos = ({result, index}) => {
const carouselId = "carouselExampleIndicators".concat(index);
const carouselIndicator = "#".concat(carouselId);

return(
<>
<div className="card">
<div className="card-body">
{result.lastUpdate !=undefined ?
<div className="ribbon-wrapper ribbon-lg">
<div className="ribbon bg-primary">
{result.lastUpdate}
</div>
</div> :''
}
<div className="row">
<div className="col-md-4">
<div id={carouselId} className="carousel slide" data-ride="carousel">
<ol className="carousel-indicators">
{result.images.map((image, i) =>
(image !== undefined && image.src !==undefined ?
i === 1 ?
<li data-target={carouselIndicator} data-slide-to={i} className="active"></li>
:
<li data-target={carouselIndicator} data-slide-to={i} className=""></li>
:""
))}
</ol>
<div className="carousel-inner">
{
result.images.map((image, i) =>
(image !== undefined && image.src !== undefined ?
i === 0 ?
<div className="carousel-item active" key={i} >
<img height="269px" className="d-block w-100"
src={image.src}
alt= {i} />
</div>
:
<div className="carousel-item" key={i} >
<img height="269px" className="d-block w-100"
src={image.src}
alt= {i} />
</div>
:'')
)
}
</div>
<a className="carousel-control-prev" href={carouselIndicator} role="button"
data-slide="prev">
<span className="carousel-control-custom-icon" aria-hidden="true">
<i className="fas fa-chevron-left"></i>
</span>
<span className="sr-only">Previous</span>
</a>
<a className="carousel-control-next" href={carouselIndicator} role="button"
data-slide="next">
<span className="carousel-control-custom-icon" aria-hidden="true">
<i className="fas fa-chevron-right"></i>
</span>
<span className="sr-only">Next</span>
</a>
</div>
</div>
<div className="col-md-8">
{result.name !== undefined ? <h2><a>{result.name}

</a>
</h2>: ''}
{result.address != undefined ?
<p className="lead">
{result.address.street !== undefined ? <span> {result.address.street}, </span>:''}
{result.address.city !== undefined ? <span> {result.address.city}, </span>:''}
{result.address.zip !== undefined ? <span> {result.address.zip.code} {result.address.zip.state}</span>:''}
</p>
: ''}
{result.rentInfo !=undefined ? <h3 className="strong">{result.rentInfo}</h3>:'' }
<p className="card-text mb-1">
{result.description !== undefined ? result.description.substr(0,100) + "..." : ''}
</p>
<div className="row">
<div className="col-md-8">
<div className="row">
<div className="col">
{
result.features.map((feature, i) => <p key={i} className="badge badge-primary">{feature}</p>)
}
</div>
</div>
<div className="row">
{ result.contact !== undefined && result.contact.phone != undefined ? <span className="mr-3 lead"><i className="fas fa-phone">{result.contact.phone}</i></span> : ''}
{ result.contact !== undefined && result.contact.agentFullName ? <span className="mr-3 lead"><i className="fas fa-user"></i>{result.contact.agentFullName}</span>: '' }
</div>
</div>
</div>

</div>
</div>
</div>
</div>
</>
);

}

CardCondos.propTypes = {
result: PropTypes.object,
index : PropTypes.string
}

export default CardCondos;

+ 122
- 0
src/components/CardHouses/CardHouses.js Просмотреть файл

import React from 'react';
import PropTypes from 'prop-types';

const CardHouses = ({result, index}) => {
const carouselId = "carouselExampleIndicators".concat(index);
const carouselIndicator = "#".concat(carouselId);

return(
<>
<div className="card">
<div className="card-body">
{result.lastUpdate !=undefined ?
<div className="ribbon-wrapper ribbon-lg">
<div className="ribbon bg-primary">
{result.lastUpdate}
</div>
</div> :''
}
<div className="row">
<div className="col-md-4">
<div id={carouselId} className="carousel slide" data-ride="carousel">
<ol className="carousel-indicators">
{result.images.map((image, i) =>
(image !== undefined && image.src !==undefined ?
i === 1 ?
<li data-target={carouselIndicator} data-slide-to={i} className="active"></li>
:
<li data-target={carouselIndicator} data-slide-to={i} className=""></li>
:""
))}
</ol>
<div className="carousel-inner">
{
result.images.map((image, i) =>
(image !== undefined && image.src !== undefined ?
i === 0 ?
<div className="carousel-item active" key={i} >
<img height="269px" className="d-block w-100"
src={image.src}
alt= {i} />
</div>
:
<div className="carousel-item" key={i} >
<img height="269px" className="d-block w-100"
src={image.src}
alt= {i} />
</div>
:'')
)
}
</div>
<a className="carousel-control-prev" href={carouselIndicator} role="button"
data-slide="prev">
<span className="carousel-control-custom-icon" aria-hidden="true">
<i className="fas fa-chevron-left"></i>
</span>
<span className="sr-only">Previous</span>
</a>
<a className="carousel-control-next" href={carouselIndicator} role="button"
data-slide="next">
<span className="carousel-control-custom-icon" aria-hidden="true">
<i className="fas fa-chevron-right"></i>
</span>
<span className="sr-only">Next</span>
</a>
</div>
</div>
<div className="col-md-8">
{result.name !== undefined ? <h2><a>{result.name}

</a>
</h2>: ''}
{result.address != undefined ?
<p className="lead">
{result.address.street !== undefined ? <span> {result.address.street}, </span>:''}
{result.address.city !== undefined ? <span> {result.address.city}, </span>:''}
{result.address.zip !== undefined ? <span> {result.address.zip.code} {result.address.zip.state}</span>:''}
</p>
: ''}
{result.rentInfo !=undefined ? <h3 className="strong">{result.rentInfo}</h3>:'' }
<p className="card-text mb-1">
{result.description !== undefined ? result.description.substr(0,100) + "..." : ''}
</p>
<div className="row">
<div className="col-md-8">
<div className="row">
<div className="col">
{
result.features.map((feature, i) => <p key={i} className="badge badge-primary">{feature}</p>)
}
</div>
</div>
<div className="row">
{ result.contact !== undefined && result.contact.phone != undefined ? <span className="mr-3 lead"><i className="fas fa-phone">{result.contact.phone}</i></span> : ''}
{ result.contact !== undefined && result.contact.agentFullName ? <span className="mr-3 lead"><i className="fas fa-user"></i>{result.contact.agentFullName}</span>: '' }
</div>
</div>
</div>

</div>
</div>
</div>
</div>
</>
);

}

CardHouses.propTypes = {
result: PropTypes.object,
index : PropTypes.string
}

export default CardHouses;

+ 1
- 1
src/components/ScrapeRequest/ScrappeStatus.jsx Просмотреть файл

const { t } = useTranslation(); const { t } = useTranslation();
console.log("id", id) console.log("id", id)
if (status === 'requested') if (status === 'requested')
return <button type="submit" className="btn btn-xs btn-block btn-primary" onClick={() => handleExecute(id)}><i className="fa fa-bell"></i>{t('common.execute')}</button>
return <button type="submit" className="btn btn-xs btn-block btn-primary" onClick={() => handleExecute(id)}><i className="fa fa-bell" ></i>{t('common.execute')}</button>
else if (status === 'done') else if (status === 'done')
return <span className='badge bg-success'>Done</span> return <span className='badge bg-success'>Done</span>
else else

+ 9
- 9
src/components/ScrappeDetails/ScrappeDetails.js Просмотреть файл

import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import ScrappeStatus from '../../components/ScrapeRequest/ScrappeStatus' import ScrappeStatus from '../../components/ScrapeRequest/ScrappeStatus'
const ScrappeDetails = (details) => {
const ScrappeDetails = ({details}) => {
const {t} = useTranslation(); const {t} = useTranslation();
return ( return (
(details.details) ?
(details) ?
<section> <section>
<h2>Scrappe Details</h2> <h2>Scrappe Details</h2>
<br/> <br/>
<div className="row"> <div className="row">
<div className="com-md-4"> <div className="com-md-4">
{ {
(details.details.location) ?
<h3>{details.details.location}</h3>
(details.location) ?
<h3>{details.location}</h3>
: ''} : ''}
{ {
(details.details.estimate) ?
<span className="text-muted">{t('scrapeRequest.EstimatedTime')} {(new Date(details.details.estimate)).toLocaleString()}</span>
(details.estimate) ?
<span className="text-muted">{t('scrapeRequest.EstimatedTime')} {(new Date(details.estimate)).toLocaleString()}</span>
: ''} : ''}
</div> </div>
<div className="col-md-4"> <div className="col-md-4">
{ {
(details.details.filters && details.details.filters.length > 0) ?
(details.filters && details.filters.length > 0) ?
<div className="filters-cont"> <div className="filters-cont">
<h3>Filters</h3> <h3>Filters</h3>
{details.details.filters.map((filter,i) => <span className="badge bg-primary m-1" key={i}>{filter.name}</span>) }
{details.filters.map((filter,i) => <span className="badge bg-primary m-1" key={i}>{filter.name}:{filter.value}</span>) }
</div> </div>
:'' } :'' }
</div> </div>
<div className="col-md-1"> <div className="col-md-1">
{details.details.status ? <ScrappeStatus status = {details.details.status} /> : '' }
{details.status ? <ScrappeStatus status = {details.status} /> : '' }
</div> </div>
</div> </div>

+ 0
- 18
src/components/ScrappeResult/ScrapeResult.js Просмотреть файл

import React from 'react';
import PropTypes from 'prop-types';

const ScrappeResult = (result) => {

return (
<div>
Result
</div>
);

}

ScrappeResult.propTypes = {
result: PropTypes.object
};

export default ScrappeResult;

+ 25
- 0
src/components/ScrappeResult/ScrappeResult.js Просмотреть файл

import React from 'react';
import PropTypes from 'prop-types';
//import CardApartments from '../CardApartments/CardApartments'
import CardHouses from '../CardHouses/CardHouses';
const ScrappeResult = ({result, type, index}) => {
return (
<>
{console.log(type)}
{
//if(type="aparments")
// <CardApartments index = {index} result={result} />

//else if(type="houses")
<CardHouses index ={index} result={result} />
}
</>
);

}
ScrappeResult.propTypes = {
result: PropTypes.object,
type: PropTypes.object,
index :PropTypes.string
};
export default ScrappeResult;

+ 2
- 0
src/constants/days.js Просмотреть файл

export const Saturday = 6;
export const Sunday = 7;

+ 3
- 0
src/constants/workingHours.js Просмотреть файл

export const WorkingDayType = 0;
export const SaturdayType = 1;
export const SundayType = 2;

+ 19
- 0
src/helpers/GetTodaysWorkingHours.js Просмотреть файл

import {Saturday, Sunday}from '../constants/days'
import {WorkingDayType, SaturdayType,SundayType }from '../constants/workingHours'

export default function getHours(officeHours) {
var day = new Date().getDay();
if(officeHours === undefined && officeHours.length < 3 ){
return null;
}
else if(day === Saturday){
return officeHours[SaturdayType].hours;
}
else if(day === Sunday){
return officeHours[SundayType].hours;
}
else {
return officeHours[WorkingDayType].hours;
}
}

+ 1
- 1
src/main.scss Просмотреть файл

@import './assets/styles/functions'; @import './assets/styles/functions';
@import './assets/styles/typography'; @import './assets/styles/typography';
@import './assets/styles/base'; @import './assets/styles/base';
@import './assets/styles/reset';
//@import './assets/styles/reset';
@import './assets/styles/components/button'; @import './assets/styles/components/button';
@import './assets/styles/components/icon-button'; @import './assets/styles/components/icon-button';
@import './assets/styles/components/app-button'; @import './assets/styles/components/app-button';

+ 3
- 1
src/pages/HomePage/HomePage.js Просмотреть файл

import CreateScrapeRequest from '../../components/CreateScrapeRequest/CreateScrapeRequest'; import CreateScrapeRequest from '../../components/CreateScrapeRequest/CreateScrapeRequest';
import ScrapeRequests from '../../components/ScrapeRequests/ScrapeRequests'; import ScrapeRequests from '../../components/ScrapeRequests/ScrapeRequests';
import { createScrappes, executeScrappes, getAllScrappes } from '../../request/scrappe'; import { createScrappes, executeScrappes, getAllScrappes } from '../../request/scrappe';

const HomePage = () => { const HomePage = () => {
const [scrappes, setScrappes] = useState([]) const [scrappes, setScrappes] = useState([])




return ( return (
<> <>
<h1 className="lead text-center" >Scrapper </h1>

<CreateScrapeRequest handleRequest={handleRequest} /> <CreateScrapeRequest handleRequest={handleRequest} />
<ScrapeRequests scrappes={scrappes} handleExecute={handleExecute} /> <ScrapeRequests scrappes={scrappes} handleExecute={handleExecute} />
</> </>

+ 14
- 7
src/pages/ScrapeResults/ScrapeResultsPage.js Просмотреть файл

import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import { getByIdScrappe } from '../../request/scrappe'; import { getByIdScrappe } from '../../request/scrappe';
import { Link } from "react-router-dom";

import ScrappeDetails from '../../components/ScrappeDetails/ScrappeDetails' import ScrappeDetails from '../../components/ScrappeDetails/ScrappeDetails'
//import ScrappeResult from '../../components/ScrappeResult/ScrappeResult'
import ScrappeResult from '../../components/ScrappeResult/ScrappeResult'
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';


const ScrapeResultsPage = ({ location }) => { const ScrapeResultsPage = ({ location }) => {


const [scrappeResults, setScrappeResults] = useState() const [scrappeResults, setScrappeResults] = useState()
const [scrappeDetails, setScrappeDetails] = useState() const [scrappeDetails, setScrappeDetails] = useState()
useEffect(() => { useEffect(() => {
getByIdScrappe(location.id) getByIdScrappe(location.id)
.then(res => { .then(res => {
setScrappeDetails(res.data) setScrappeDetails(res.data)
if(res.data.status==='done') if(res.data.status==='done')
setScrappeResults(res.data.result)}) setScrappeResults(res.data.result)})
}, [setScrappeResults]) }, [setScrappeResults])
return ( return (
<> <>
{/* ScrappeDetail */}
{console.log(scrappeDetails)}
<Link to="/" className="navbar-brand">
<span className="brand-text font-weight-light">Back</span>
</Link>
<ScrappeDetails details = {scrappeDetails} /> <ScrappeDetails details = {scrappeDetails} />
{/* {(scrappeResults !==undefined)
? scrappeResults.map((result, i) => <ScrappeResult key={i} result = {result} />)
:''
*/}
<div className ='content' >
{(scrappeResults !== undefined) ?
scrappeResults.map((result, i) => <ScrappeResult key={i} index={i} type ={scrappeDetails.filters.find(el => el.name="type")} result = {result} />)
:''
}
</div>
</> </>
); );
}; };

+ 1079
- 22
yarn.lock
Разница между файлами не показана из-за своего большого размера
Просмотреть файл


Загрузка…
Отмена
Сохранить