-
-
Save aversan/f72a78dfa040ee2f36fc9a096f7b2393 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React, { Component } from 'react'; | |
import PropTypes from 'prop-types'; | |
import classNames from 'classnames'; | |
import shortid from 'shortid'; | |
import Row from 'reactstrap/lib/Row'; | |
import Col from 'reactstrap/lib/Col'; | |
import Input from 'reactstrap/lib/Input'; | |
import FormGroup from 'reactstrap/lib/FormGroup'; | |
import { FULL_MONTH } from '../../../helpers/date'; | |
import { FILTER_PREMIERE, FILTER_ALL } from '../../../actions/active-filter'; | |
import colWidths from '../../../helpers/col-widths'; | |
import Title from '../../../shared/title/title'; | |
import './afisha-header.scss'; | |
const renderOption = item => ( | |
<option key={shortid.generate()} value={item.value}> | |
{item.name} | |
</option> | |
); | |
class AfishaHeader extends Component { | |
constructor(props) { | |
super(props); | |
this.state = { | |
currencyMonths: '-1', | |
currencyGroup: FILTER_ALL, | |
}; | |
} | |
onMonthsChange = (event) => { | |
const { value } = event.target; | |
this.setState({ | |
currencyMonths: value, | |
}); | |
this.props.changeFilter({ type: 'month', value: parseInt(value) }); | |
}; | |
onGroupChange = (event) => { | |
const { value } = event.target; | |
this.setState({ | |
currencyGroup: value, | |
}); | |
this.props.changeFilter({ type: 'group', value }); | |
}; | |
render() { | |
const { className, months } = this.props; | |
return ( | |
<div | |
className={classNames('afisha-header', className)} | |
> | |
<Row className="align-items-center"> | |
<Col widths={colWidths} xs="12" lg="6" xxl="6"> | |
<Title title="Афиша" as="h1" size={1} page /> | |
</Col> | |
<Col widths={colWidths} xs="12" md="6" lg="3" xxl="3"> | |
<FormGroup className="mb-md-0 mt-lg-2 mt-xl-3"> | |
<Input | |
type="select" | |
className="custom-select w-wide" | |
onChange={this.onMonthsChange} | |
value={this.state.currencyMonths} | |
> | |
{renderOption({ value: -1, name: 'Месяц' })} | |
{ | |
months && | |
months.map(month => | |
renderOption({ value: month, name: FULL_MONTH[month] }) | |
) | |
} | |
</Input> | |
</FormGroup> | |
</Col> | |
<Col widths={colWidths} xs="12" md="6" lg="3" xxl="3"> | |
<FormGroup className="mb-md-0 mt-lg-2 mt-xl-3"> | |
<Input | |
type="select" | |
className="custom-select w-wide" | |
onChange={this.onGroupChange} | |
value={this.state.currencyGroup} | |
> | |
{renderOption({ value: FILTER_ALL, name: 'Все спектакли' })} | |
{renderOption({ value: FILTER_PREMIERE, name: 'Премьеры' })} | |
</Input> | |
</FormGroup> | |
</Col> | |
</Row> | |
</div> | |
); | |
} | |
} | |
AfishaHeader.propTypes = { | |
months: PropTypes.arrayOf(PropTypes.oneOf([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])), | |
changeFilter: PropTypes.func, | |
className: PropTypes.string, | |
}; | |
AfishaHeader.defaultProps = { | |
months: null, | |
changeFilter: null, | |
className: '', | |
}; | |
export default AfishaHeader; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React from 'react'; | |
import { render } from 'react-dom'; | |
import { BrowserRouter as Router, Route } from 'react-router-dom'; | |
import createBrowserHistory from 'history/createBrowserHistory'; | |
import { Provider } from 'react-redux'; | |
import isMobile from 'is-mobile'; | |
import configureStore from './store/configureStore'; | |
import Header from './shared/header/header'; | |
import MainPage from './pages/main-page/container'; | |
import PerformancePage from './pages/performance-page/container'; | |
import ProfilePage from './pages/profile-page/container'; | |
import PerformancesPage from './pages/performances-page/container'; | |
import NewsPage from './pages/news-page/container'; | |
import NewsPostPage from './pages/news-post-page/container'; | |
import CollectivePage from './pages/collective-page/container'; | |
import AfishaPage from './pages/afisha-page/container'; | |
import Layout from './shared/layout/layout'; | |
import LayoutHeader from './shared/layout/layout-header/layout-header'; | |
import Menu from './pages/menu/container'; | |
import './app.scss'; | |
const store = configureStore(); | |
const history = createBrowserHistory(); | |
render( | |
<Provider store={store}> | |
<Router history={history}> | |
<div className={isMobile() ? 'is-mobile' : ''}> | |
<Layout> | |
<LayoutHeader element="header"> | |
<Header /> | |
</LayoutHeader> | |
<Route exact path="/performances/:id" component={PerformancePage} /> | |
<Route exact path="/performances" component={PerformancesPage} /> | |
<Route exact path="/" component={MainPage} /> | |
<Route exact path="/collective" component={CollectivePage} /> | |
<Route exact path="/profiles" component={CollectivePage} /> | |
<Route exact path="/afisha" component={AfishaPage} /> | |
<Route exact path="/articles/:id" component={NewsPostPage} /> | |
<Route exact path="/articles" component={NewsPage} /> | |
</Layout> | |
<Route exact path="/profiles/:id" component={ProfilePage} /> | |
<Route exact path="/menu" component={Menu} /> | |
</div> | |
</Router> | |
</Provider> | |
, | |
document.getElementById('react-app-container'), | |
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// fonts | |
@import 'styles/fonts'; | |
// bootstrap base | |
@import '../node_modules/bootstrap/scss/print'; | |
@import '../node_modules/bootstrap/scss/reboot'; | |
@import '../node_modules/bootstrap/scss/type'; | |
@import '../node_modules/bootstrap/scss/grid'; | |
@import '../node_modules/bootstrap/scss/images'; | |
@import '../node_modules/bootstrap/scss/nav'; | |
@import '../node_modules/bootstrap/scss/forms'; | |
// global | |
@import 'styles/global'; | |
@import 'styles/forms'; | |
@import 'styles/custom-forms'; | |
// bootstrap utilities | |
//@import '../node_modules/bootstrap/scss/utilities/align'; | |
//@import '../node_modules/bootstrap/scss/utilities/background'; | |
//@import '../node_modules/bootstrap/scss/utilities/borders'; | |
//@import '../node_modules/bootstrap/scss/utilities/clearfix'; | |
@import '../node_modules/bootstrap/scss/utilities/display'; | |
@import '../node_modules/bootstrap/scss/utilities/embed'; | |
@import '../node_modules/bootstrap/scss/utilities/flex'; | |
//@import '../node_modules/bootstrap/scss/utilities/float'; | |
@import '../node_modules/bootstrap/scss/utilities/position'; | |
@import '../node_modules/bootstrap/scss/utilities/screenreaders'; | |
//@import '../node_modules/bootstrap/scss/utilities/sizing'; | |
@import '../node_modules/bootstrap/scss/utilities/spacing'; | |
@import '../node_modules/bootstrap/scss/utilities/text'; | |
@import '../node_modules/bootstrap/scss/utilities/visibility'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React from 'react'; | |
import PropTypes from 'prop-types'; | |
import shortid from 'shortid'; | |
import { groupBy, sortBy, uniq } from 'underscore'; | |
import Row from 'reactstrap/lib/Row'; | |
import Col from 'reactstrap/lib/Col'; | |
import { FULL_MONTH, dateDateMonthDayString } from '../../../helpers/date'; | |
import { FILTER_ALL, FILTER_PREMIERE } from '../../../actions/active-filter'; | |
import colWidths from '../../../helpers/col-widths'; | |
import Title from '../../../shared/title/title'; | |
import Lines from '../../../shared/lines/lines'; | |
import AfishaItem from './afisha-item/afisha-item'; | |
const renderItem = item => ( | |
<AfishaItem {...item} key={`item-${shortid.generate()}`} /> | |
); | |
const renderItems = items => ( | |
<Col widths={colWidths} xs="12" md="9" className="lines-items"> | |
{items.map(item => renderItem(item))} | |
</Col> | |
); | |
const renderDate = (date) => { | |
const dateTemp = dateDateMonthDayString(new Date(date)); | |
const dateText = dateTemp.split(' '); | |
return ( | |
<Col widths={colWidths} xs="12" md="3"> | |
<div className="lines-group-date text-uppercase h2 mb-0 py-md-3 d-md-flex flex-md-column flex-lg-row align-items-lg-center"> | |
<span>{dateText[0]} </span> | |
<span className="typo-sm d-lg-flex flex-lg-column pl-lg-1"> | |
<span>{dateText[1]}</span> | |
<span className="d-lg-none">, </span> | |
<span>{dateText[2]}</span> | |
</span> | |
</div> | |
</Col> | |
); | |
}; | |
const Afisha = ({ items, setAfishaMonths, activeMonth, activeGroup }) => { | |
let filteredItems = items; | |
if (activeMonth && activeMonth !== -1) { | |
filteredItems = filteredItems.filter(item => new Date(item.releaseDate).getMonth() === activeMonth); | |
} | |
if (activeGroup && activeGroup !== FILTER_ALL) { | |
filteredItems = filteredItems.filter(item => item.premiere && activeGroup === FILTER_PREMIERE); | |
} | |
const groups = groupBy(items, 'releaseDate'); | |
const groupKeys = Object.keys(groups); | |
const filteredGroups = groupBy(filteredItems, 'releaseDate'); | |
const filteredGroupKeys = Object.keys(filteredGroups); | |
if (groupKeys.length > 0) { | |
let months = groupKeys.map(date => new Date(date).getMonth()); | |
months = uniq(months); | |
months = months.sort(); | |
setAfishaMonths(months); | |
} | |
return ( | |
<Lines className="afisha"> | |
{ | |
activeMonth && | |
FULL_MONTH[activeMonth] && | |
<Title title={FULL_MONTH[activeMonth]} as="h3" size={3} uppercase className="lines-group-title d-none d-md-block" /> | |
} | |
<div className="lines-group-container"> | |
{ | |
(filteredGroupKeys.length > 0) && | |
filteredGroupKeys.map(date => ( | |
<Row className="lines-group pb-1 pb-md-0 mb-1 mb-md-0" key={`item-${shortid.generate()}`}> | |
{renderDate(date)} | |
{renderItems(sortBy(filteredGroups[date], 'time'))} | |
</Row> | |
)) | |
} | |
</div> | |
</Lines> | |
); | |
}; | |
Afisha.propTypes = { | |
items: PropTypes.arrayOf(PropTypes.shape), | |
setAfishaMonths: PropTypes.func, | |
activeMonth: PropTypes.number, | |
activeGroup: PropTypes.string, | |
}; | |
Afisha.defaultProps = { | |
items: null, | |
setAfishaMonths: null, | |
activeMonth: null, | |
activeGroup: null, | |
}; | |
export default Afisha; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
$x-mobile: map-get($spacers, 2); | |
$x-desktop: map-get($spacers, 4); | |
.main-hero { | |
&-container { | |
position: relative; | |
margin-top: -$header-height-breakpoint-desktop; | |
height: 100vh; | |
@include media-breakpoint-down(sm) { | |
margin-top: -$header-height-breakpoint-mobile; | |
} | |
} | |
&-icon-down { | |
cursor: pointer; | |
width: 24px; | |
height: 24px; | |
position: absolute; | |
left: 50%; | |
margin-left: -12px; | |
bottom: ($header-height-breakpoint-mobile - 1.625rem) / 2; | |
z-index: 2; | |
@include media-breakpoint-up(md) { | |
bottom: ($header-height-breakpoint-desktop - 2.875rem) / 2; | |
} | |
.icon { | |
position: absolute; | |
left: 50%; | |
top: 50%; | |
&-arrow-down { | |
margin-left: -12px; | |
margin-top: -6px; | |
} | |
} | |
} | |
&-image-container { | |
position: relative; | |
width: 63%; | |
@include media-breakpoint-down(xl) { | |
width: 64.5%; | |
} | |
@include media-breakpoint-down(lg) { | |
width: 66%; | |
} | |
@include media-breakpoint-down(md) { | |
width: calc(100% - #{$x-desktop}); | |
} | |
@include media-breakpoint-down(sm) { | |
width: calc(100% + #{2 * $x-mobile}); | |
margin-left: -$x-mobile; | |
margin-right: -$x-mobile; | |
} | |
} | |
&-logo-container { | |
width: 100%; | |
} | |
&-image.embed-responsive, | |
&-logo-wrapper.embed-responsive { | |
padding-top: 56.25%; | |
position: absolute; | |
left: 50%; | |
top: 50%; | |
transform: translate(-50%, -50%); | |
height: 0; | |
} | |
&-image.embed-responsive, | |
&-logo-wrapper.embed-responsive { | |
min-width: 444px; | |
min-height: 320px; | |
} | |
&-logo-1, | |
&-logo-2 { | |
position: absolute; | |
transform: scale(0.75); | |
@include media-breakpoint-down(xl) { | |
transform: scale(0.87); | |
} | |
@include media-breakpoint-down(lg) { | |
transform: scale(0.75); | |
} | |
@include media-breakpoint-down(md) { | |
transform: scale(1); | |
} | |
@include media-breakpoint-down(sm) { | |
transform: scale(0.66); | |
} | |
&, | |
& svg { | |
width: 100%; | |
height: auto; | |
} | |
} | |
&-logo-1 { | |
left: 0; | |
top: 24.5%; | |
@include media-breakpoint-down(xl) { | |
top: 22%; | |
} | |
@include media-breakpoint-down(lg) { | |
top: 24%; | |
} | |
@include media-breakpoint-down(md) { | |
top: 18.5%; | |
} | |
@include media-breakpoint-down(sm) { | |
top: 31%; | |
} | |
} | |
&-logo-2 { | |
right: 0; | |
bottom: 24.5%; | |
@include media-breakpoint-down(xl) { | |
bottom: 22%; | |
} | |
@include media-breakpoint-down(lg) { | |
bottom: 24%; | |
} | |
@include media-breakpoint-down(md) { | |
bottom: 18.5%; | |
} | |
@include media-breakpoint-down(sm) { | |
bottom: 31%; | |
} | |
} | |
} | |
.main-hero-animated { | |
&.main-hero-logo-wrapper.embed-responsive { | |
padding-top: 0; | |
left: 0; | |
top: 0; | |
transform: translate(0, 0); | |
height: 100vh; | |
} | |
&.main-hero-logo-1, | |
&.main-hero-logo-2 { | |
width: 362px; | |
height: $header-height-breakpoint-mobile; | |
transform: scale(1); | |
@include media-breakpoint-up(md) { | |
height: $header-height-breakpoint-desktop; | |
} | |
svg { | |
position: relative; | |
top: 50%; | |
transform: translateY(-50%); | |
} | |
@include media-breakpoint-down(sm) { | |
width: 186px; | |
} | |
} | |
&.main-hero-logo-1 { | |
top: 0; | |
} | |
&.main-hero-logo-2 { | |
bottom: 0; | |
} | |
} | |
.main-hero-animated-finish { | |
&.main-hero-logo-1, | |
&.main-hero-logo-2 { | |
opacity: 0; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React, { Component } from 'react'; | |
import PropTypes from 'prop-types'; | |
import Col from 'reactstrap/lib/Col'; | |
import Scroll from 'react-scroll'; | |
import { PerformanceApi, PerformancesApi } from '../../services/api/PerformancesApi'; | |
import { CollectiveApi } from '../../services/api/CollectiveApi'; | |
import { AfishaApi } from '../../services/api/AfishaApi'; | |
import colWidths from '../../helpers/col-widths'; | |
import LayoutBody from '../../shared/layout/layout-body/layout-body'; | |
import LayoutRow from '../../shared/layout/layout-row/layout-row'; | |
import PromoBanner from '../../shared/promo-banner/promo-banner'; | |
import Title from '../../shared/title/title'; | |
import Divider from '../../shared/divider/divider'; | |
import Sidenav from '../../shared/sidenav/sidenav'; | |
import PerformanceInfo from './perfomance-info/perfomance-info'; | |
import Information from './information/information'; | |
import Gallery from './gallery/gallery'; | |
import Collective from './collective/collective'; | |
import Press from './press/press'; | |
import UpcomingDates from './upcoming-dates/upcoming-dates'; | |
import OtherPerformances from './other-perfomances/other-performances'; | |
const ScrollElement = Scroll.Element; | |
export default class PerformancePage extends Component { | |
static propTypes = { | |
name: PropTypes.string.isRequired, | |
title: PropTypes.string.isRequired, | |
duration: PropTypes.number.isRequired, | |
directors: PropTypes.oneOfType([ | |
PropTypes.string, | |
PropTypes.arrayOf(PropTypes.string), | |
]), | |
ageLimit: PropTypes.number.isRequired, | |
image: PropTypes.string, | |
images: PropTypes.arrayOf(PropTypes.string), | |
description: PropTypes.string.isRequired, | |
creativeTeam: PropTypes.arrayOf(PropTypes.shape), | |
actors: PropTypes.arrayOf(PropTypes.shape), | |
press: PropTypes.arrayOf(PropTypes.shape), | |
relatedPerformances: PropTypes.arrayOf(PropTypes.shape), | |
performanceSchedules: PropTypes.arrayOf(PropTypes.shape), | |
match: PropTypes.shape(), | |
setData: PropTypes.func, | |
}; | |
static defaultProps = { | |
directors: null, | |
image: null, | |
images: null, | |
creativeTeam: null, | |
actors: null, | |
press: null, | |
relatedPerformances: null, | |
performanceSchedules: null, | |
match: null, | |
setData: null, | |
}; | |
setData = (id) => { | |
PerformanceApi.performance(id) | |
.then((response) => { | |
const { | |
name, | |
title, | |
duration, | |
directors, | |
age_limit, | |
image, | |
images, | |
description, | |
creative_team, | |
articles, | |
actors, | |
related_performances, | |
performance_schedules, | |
} = response; | |
const data = { | |
name, | |
title, | |
duration, | |
directors, | |
ageLimit: age_limit, | |
image, | |
images, | |
description, | |
creativeTeam: PerformanceApi.formatCreativeTeam(creative_team), | |
actors: CollectiveApi.formatPerformanceTeam(actors).items, | |
press: articles, | |
relatedPerformances: PerformancesApi.formatPerformances(related_performances).items, | |
performanceSchedules: AfishaApi.formatAfisha(performance_schedules).items, | |
}; | |
this.props.setData(data); | |
}); | |
}; | |
componentDidMount() { | |
const id = parseInt(this.props.match.params.id, 10); | |
this.setData(id); | |
} | |
render() { | |
const { | |
name, | |
title, | |
duration, | |
directors, | |
ageLimit, | |
image, | |
description, | |
images, | |
creativeTeam, | |
actors, | |
press, | |
performanceSchedules, | |
relatedPerformances, | |
} = this.props; | |
return ( | |
<LayoutBody> | |
<Sidenav className="d-none d-xl-block" type="performance" /> | |
<Title title={name} as="h1" size={1} page /> | |
<PerformanceInfo title={title} duration={duration} directors={directors} ageLimit={ageLimit} /> | |
<LayoutRow> | |
<Col widths={colWidths} xs="12" xl="9" className="layout-content ml-auto"> | |
{ | |
image && | |
<div> | |
<Divider type="section" /> | |
<PromoBanner image={image} /> | |
</div> | |
} | |
{ | |
description && | |
<div> | |
<Divider type="section" /> | |
<ScrollElement name="information"> | |
<Information description={description} /> | |
</ScrollElement> | |
</div> | |
} | |
{ | |
images && | |
<div> | |
<Divider type="section" /> | |
<Gallery images={images} /> | |
</div> | |
} | |
{ | |
(creativeTeam || actors) && | |
<div> | |
<Divider type="section" /> | |
<ScrollElement name="collective"> | |
<Collective creativeTeam={creativeTeam} actors={actors} /> | |
</ScrollElement> | |
</div> | |
} | |
{ | |
press && | |
<div> | |
<Divider type="section" /> | |
<ScrollElement name="press"> | |
<Press items={press} /> | |
</ScrollElement> | |
</div> | |
} | |
{ | |
performanceSchedules && | |
<div> | |
<Divider type="section" /> | |
<ScrollElement name="dates"> | |
<UpcomingDates /> | |
</ScrollElement> | |
</div> | |
} | |
</Col> | |
</LayoutRow> | |
{ | |
relatedPerformances && | |
<div> | |
<Divider type="section" /> | |
<OtherPerformances items={relatedPerformances} /> | |
</div> | |
} | |
</LayoutBody> | |
); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React, { Component } from 'react'; | |
import PropTypes from 'prop-types'; | |
import classNames from 'classnames'; | |
import Row from 'reactstrap/lib/Row'; | |
import Col from 'reactstrap/lib/Col'; | |
import Input from 'reactstrap/lib/Input'; | |
import FormGroup from 'reactstrap/lib/FormGroup'; | |
import shortid from 'shortid'; | |
import { FILTER_CURRENT, FILTER_PREMIERE, FILTER_SPECIAL, FILTER_ARCHIVE, FILTER_ALL } from '../../../actions/active-filter'; | |
import { filterMap } from './filter-map'; | |
import colWidths from '../../../helpers/col-widths'; | |
import Title from '../../../shared/title/title'; | |
import './performances-header.scss'; | |
const renderCheckbox = (item, onChangeHandler, active) => ( | |
<Col widths={colWidths} xs="3" key={shortid.generate()}> | |
<label className="custom-control custom-checkbox text-uppercase mb-0 mr-0 d-inline-flex flex-column align-items-center justify-content-center" htmlFor={item.slug}> | |
<Input | |
type="checkbox" | |
className="custom-control-input" | |
id={item.slug} | |
value={item.slug} | |
onChange={onChangeHandler} | |
checked={active === item.slug} | |
/> | |
<span className="custom-control-indicator" /> | |
<span className="custom-control-description d-flex flex-column"> | |
<span>{item.name}</span> | |
<span className="d-none d-lg-inline">{item.qnt}</span> | |
</span> | |
</label> | |
</Col> | |
); | |
const renderOption = item => ( | |
<option key={shortid.generate()} value={item.slug}> | |
{item.name} | |
</option> | |
); | |
class PerformancesHeader extends Component { | |
constructor(props) { | |
super(props); | |
this.state = { | |
currency: props.active, | |
}; | |
} | |
onSelectChange = (event) => { | |
const { value } = event.target; | |
this.setState({ | |
currency: value, | |
}); | |
this.props.changeActiveFilter(value); | |
}; | |
onCheckboxChange = (event) => { | |
const { checked, value } = event.target; | |
if (checked) { | |
this.setState({ | |
currency: value, | |
}); | |
this.props.changeActiveFilter(value); | |
} else { | |
this.setState({ | |
currency: FILTER_ALL, | |
}); | |
this.props.changeActiveFilter(FILTER_ALL); | |
} | |
}; | |
render() { | |
const { categories, className } = this.props; | |
return ( | |
<div | |
className={classNames('performances-header text-md-center text-lg-left', className)} | |
> | |
<Title title="Репертуар" as="h1" size={1} page /> | |
{ | |
categories && | |
<div> | |
<Row className="d-none d-md-flex"> | |
{ | |
categories.map(item => | |
!!item.qnt && | |
filterMap.includes(item.slug) && | |
renderCheckbox(item, this.onCheckboxChange, this.state.currency) | |
) | |
} | |
</Row> | |
<Row className="d-md-none"> | |
<Col widths={colWidths} xs="12"> | |
<FormGroup className="mb-0 mt-lg-2 mt-xl-3"> | |
<Input | |
type="select" | |
className="custom-select w-wide" | |
onChange={this.onSelectChange} | |
value={this.state.currency} | |
> | |
{ | |
renderOption({ slug: FILTER_ALL, name: 'Все' }) | |
} | |
{ | |
categories.map(item => | |
!!item.qnt && | |
filterMap.includes(item.slug) && | |
renderOption(item) | |
) | |
} | |
</Input> | |
</FormGroup> | |
</Col> | |
</Row> | |
</div> | |
} | |
</div> | |
); | |
} | |
} | |
PerformancesHeader.propTypes = { | |
categories: PropTypes.arrayOf(PropTypes.shape({ | |
name: PropTypes.string, | |
slug: PropTypes.string, | |
qnt: PropTypes.number, | |
})), | |
className: PropTypes.string, | |
active: PropTypes.oneOf([FILTER_CURRENT, FILTER_PREMIERE, FILTER_SPECIAL, FILTER_ARCHIVE, FILTER_ALL]), | |
changeActiveFilter: PropTypes.func, | |
}; | |
PerformancesHeader.defaultProps = { | |
categories: null, | |
className: '', | |
active: FILTER_ALL, | |
changeActiveFilter: null, | |
}; | |
export default PerformancesHeader; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React, { Component } from 'react'; | |
import PropTypes from 'prop-types'; | |
import { Redirect } from 'react-router-dom'; | |
import Col from 'reactstrap/lib/Col'; | |
import Row from 'reactstrap/lib/Row'; | |
import { ProfileApi } from '../../services/api/ProfileApi'; | |
import { PerformancesApi } from '../../services/api/PerformancesApi'; | |
import colWidths from '../../helpers/col-widths'; | |
import Header from '../../shared/header/header'; | |
import Title from '../../shared/title/title'; | |
import Divider from '../../shared/divider/divider'; | |
import TextGroup from '../../shared/text-group/text-group'; | |
import Layout from '../../shared/layout/layout'; | |
import LayoutHeader from '../../shared/layout/layout-header/layout-header'; | |
import LayoutBody from '../../shared/layout/layout-body/layout-body'; | |
import LayoutRow from '../../shared/layout/layout-row/layout-row'; | |
import LayoutImage from '../../shared/layout/layout-image/layout-image'; | |
import Movies from './movies/movies'; | |
import Performances from './performances/performances'; | |
export default class ProfilePage extends Component { | |
static propTypes = { | |
fullName: PropTypes.string, | |
categories: PropTypes.arrayOf(PropTypes.string), | |
image: PropTypes.string, | |
birthYear: PropTypes.number, | |
description: PropTypes.string, | |
performances: PropTypes.arrayOf(PropTypes.shape), | |
movies: PropTypes.arrayOf(PropTypes.shape), | |
setData: PropTypes.func, | |
location: PropTypes.shape(), | |
match: PropTypes.shape(), | |
profiles: PropTypes.arrayOf(PropTypes.number), | |
}; | |
static defaultProps = { | |
fullName: '', | |
categories: null, | |
image: '', | |
birthYear: 0, | |
description: '', | |
performances: null, | |
movies: null, | |
setData: null, | |
showModal: null, | |
location: null, | |
match: null, | |
profiles: null, | |
}; | |
state = { | |
visible: true, | |
from: '', | |
}; | |
constructor(props) { | |
super(props); | |
this.from = (props.location.state && props.location.state.from) ? props.location.state.from : '/'; | |
} | |
componentDidMount() { | |
const id = parseInt(this.props.match.params.id, 10); | |
this.setData(id); | |
} | |
setData = (profileId) => { | |
ProfileApi.profile(profileId) | |
.then((response) => { | |
const { performances, movies } = response; | |
const data = { | |
...ProfileApi.formatProfile(response), | |
performances: PerformancesApi.formatPerformances(performances).items, | |
movies: ProfileApi.formatMovies(movies).items, | |
}; | |
this.props.setData(data); | |
}); | |
}; | |
componentWillReceiveProps(nextProps) { | |
const currentId = parseInt(this.props.match.params.id, 10); | |
const nextId = parseInt(nextProps.match.params.id, 10); | |
if (currentId !== nextId) { | |
this.props.setData(nextId); | |
} | |
} | |
profileClose = () => { | |
this.setState({ visible: false }); | |
}; | |
render() { | |
const { fullName, categories, image, description, birthYear, performances, movies, profiles } = this.props; | |
const { visible } = this.state; | |
const id = parseInt(this.props.match.params.id, 10); | |
const currentIndex = profiles && profiles.indexOf(id); | |
const prevId = profiles && ((currentIndex === 0) ? profiles[profiles.length - 1] : profiles[currentIndex - 1]); | |
const nextId = profiles && ((currentIndex === profiles.length - 1) ? profiles[0] : profiles[currentIndex + 1]); | |
if (this.from && !visible) { | |
return <Redirect to={this.from} />; | |
} else if (!visible) { | |
return <Redirect to="/" />; | |
} | |
return ( | |
<Layout modal type="profile"> | |
<LayoutHeader> | |
<Header modal type="profile" prevProfileId={prevId} nextProfileId={nextId} profileClose={this.profileClose} /> | |
</LayoutHeader> | |
<LayoutBody> | |
<LayoutRow> | |
<Col widths={colWidths} xs="12" xl="7" className="layout-content ml-auto"> | |
<Row> | |
<Col widths={colWidths} xs="12" lg="6" xl="12" className="order-1 text-center text-lg-left"> | |
{ | |
fullName && | |
<Title title={fullName} page name className="layout-title mb-xxl-4" /> | |
} | |
<Row> | |
<Col widths={colWidths} xs="6"> | |
{ | |
categories && | |
<TextGroup title="Категория"> | |
<span>{categories && categories.join(', ')}</span> | |
</TextGroup> | |
} | |
</Col> | |
<Col widths={colWidths} xs="6"> | |
{ | |
!!birthYear && | |
<TextGroup title="Год рождения"> | |
<span>{birthYear}</span> | |
</TextGroup> | |
} | |
</Col> | |
</Row> | |
</Col> | |
<Col widths={colWidths} xs="12" lg="6" xl="12" className="order-3"> | |
{ | |
description && | |
<div> | |
<Divider type="section" /> | |
<div className="profile-text"> | |
{description} | |
</div> | |
</div> | |
} | |
</Col> | |
<Col widths={colWidths} xs="12" md="9" lg="6" xl="5" className="order-2 mx-auto layout-image-wrapper"> | |
{ | |
image && | |
<div> | |
<Divider type="section" className="d-lg-none" /> | |
<LayoutImage image={image} /> | |
</div> | |
} | |
</Col> | |
{ | |
performances && | |
<Col widths={colWidths} xs="12" className="order-12"> | |
<Divider /> | |
<Performances items={performances} /> | |
</Col> | |
} | |
{ | |
movies && | |
<Col widths={colWidths} xs="12" className="order-12"> | |
<Movies items={movies} /> | |
</Col> | |
} | |
</Row> | |
</Col> | |
</LayoutRow> | |
</LayoutBody> | |
</Layout> | |
); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment