|
1 | | -/* eslint-disable react/prop-types */ |
2 | | -import React from 'react'; |
| 1 | +import React, { useState } from 'react'; |
3 | 2 | import { |
4 | 3 | MultiList, |
5 | 4 | ReactiveBase, |
6 | 5 | ReactiveList, |
7 | 6 | SearchBox, |
8 | 7 | SelectedFilters, |
9 | 8 | getServerState, |
| 9 | + RangeSlider, |
10 | 10 | } from '@appbaseio/reactivesearch'; |
| 11 | +import PropTypes from 'prop-types'; |
11 | 12 |
|
12 | | -const Main = (props) => { |
13 | | - function booksReactiveList(data) { |
14 | | - return ( |
15 | | - <div className="flex book-content" key={data._id}> |
16 | | - <img src={data.image} alt="Book Cover" className="book-image" /> |
17 | | - <div className="flex column justify-center" style={{ marginLeft: 20 }}> |
18 | | - <div className="book-header">{data.original_title}</div> |
19 | | - <div className="flex column justify-space-between"> |
20 | | - <div> |
21 | | - <div> |
22 | | - by <span className="authors-list">{data.authors}</span> |
| 13 | +function Main(props) { |
| 14 | + const [isClicked, setIsClicked] = useState(false); |
| 15 | + const [message, setMessage] = useState('🔬 Show Filters'); |
| 16 | + |
| 17 | + const handleClick = () => { |
| 18 | + setIsClicked(!isClicked); |
| 19 | + setMessage(isClicked ? '🔬 Show Filters' : '🎬 Show Movies'); |
| 20 | + }; |
| 21 | + |
| 22 | + return ( |
| 23 | + <div className="main-container"> |
| 24 | + <ReactiveBase |
| 25 | + app="movies-demo-app" |
| 26 | + url="https://81719ecd9552:e06db001-a6d8-4cc2-bc43-9c15b1c0c987@appbase-demo-ansible-abxiydt-arc.searchbase.io" |
| 27 | + enableAppbase |
| 28 | + theme={{ |
| 29 | + colors: { |
| 30 | + backgroundColor: '#212121', |
| 31 | + primaryTextColor: '#fff', |
| 32 | + primaryColor: '#2196F3', |
| 33 | + titleColor: '#fff', |
| 34 | + alertColor: '#d9534f', |
| 35 | + borderColor: '#666', |
| 36 | + }, |
| 37 | + }} |
| 38 | + {...(props.contextCollector ? { contextCollector: props.contextCollector } : {})} |
| 39 | + initialState={props.initialState} |
| 40 | + > |
| 41 | + <div className="navbar"> |
| 42 | + <div className="header-container"> |
| 43 | + <span role="img" aria-label="movies-emoji"> |
| 44 | + 🎥 |
| 45 | + </span>{' '} |
| 46 | + MovieSearch |
| 47 | + </div> |
| 48 | + |
| 49 | + <div className="search-container"> |
| 50 | + <SearchBox |
| 51 | + componentId="SearchSensor" |
| 52 | + dataField={['original_title', 'original_title.search']} |
| 53 | + autosuggest |
| 54 | + placeholder="Search for movies..." |
| 55 | + iconPosition="left" |
| 56 | + className="search" |
| 57 | + highlight |
| 58 | + URLParams |
| 59 | + /> |
| 60 | + </div> |
| 61 | + <div className="sub-container"> |
| 62 | + <div className={isClicked ? 'left-bar-optional' : 'left-bar'}> |
| 63 | + <div className="filter-heading center"> |
| 64 | + <b> |
| 65 | + {' '} |
| 66 | + <i className="fa fa-pied-piper-alt" /> Genres{' '} |
| 67 | + </b> |
23 | 68 | </div> |
24 | | - <div className="ratings-list flex align-center"> |
25 | | - <span className="stars"> |
26 | | - { |
27 | | - Array(data.average_rating_rounded) |
28 | | - .fill('x') |
29 | | - .map((item, index) => ( |
30 | | - // eslint-disable-next-line react/no-array-index-key |
31 | | - <i className="fas fa-star" key={index} /> |
32 | | - )) // eslint-disable-line |
33 | | - } |
34 | | - </span> |
35 | | - <span className="avg-rating">({data.average_rating} avg)</span> |
| 69 | + |
| 70 | + <MultiList |
| 71 | + componentId="GenresList" |
| 72 | + dataField="genres.keyword" |
| 73 | + react={{ |
| 74 | + and: ['SearchSensor', 'results', 'VoteAverage'], |
| 75 | + }} |
| 76 | + innerClass={{ |
| 77 | + label: 'list-item', |
| 78 | + input: 'list-input', |
| 79 | + }} |
| 80 | + URLParams |
| 81 | + className="genres-filter" |
| 82 | + /> |
| 83 | + <hr className="blue" /> |
| 84 | + |
| 85 | + <div className="filter-heading center"> |
| 86 | + <b> |
| 87 | + <i className="fa fa-star" /> Ratings |
| 88 | + </b> |
36 | 89 | </div> |
| 90 | + <RangeSlider |
| 91 | + componentId="VoteAverage" |
| 92 | + dataField="vote_average" |
| 93 | + range={{ |
| 94 | + start: 0, |
| 95 | + end: 10, |
| 96 | + }} |
| 97 | + rangeLabels={{ |
| 98 | + start: '0', |
| 99 | + end: '10', |
| 100 | + }} |
| 101 | + react={{ |
| 102 | + and: ['SearchSensor', 'results', 'GenresList'], |
| 103 | + }} |
| 104 | + showHistogram |
| 105 | + URLParams |
| 106 | + className="review-filter" |
| 107 | + /> |
37 | 108 | </div> |
38 | | - <span className="pub-year">Pub {data.original_publication_year}</span> |
39 | | - </div> |
40 | | - </div> |
41 | | - </div> |
42 | | - ); |
43 | | - } |
44 | 109 |
|
45 | | - return ( |
46 | | - <ReactiveBase |
47 | | - app="good-books-ds" |
48 | | - url="https://a03a1cb71321:75b6603d-9456-4a5a-af6b-a487b309eb61@appbase-demo-ansible-abxiydt-arc.searchbase.io" |
49 | | - enableAppbase |
50 | | - {...(props.contextCollector ? { contextCollector: props.contextCollector } : {})} |
51 | | - initialState={props.initialState} |
52 | | - > |
53 | | - <div className="row"> |
54 | | - <div className="col"> |
55 | | - <SearchBox componentId="SearchBox" dataField="original_title" URLParams /> |
56 | | - <MultiList |
57 | | - componentId="BookSensor" |
58 | | - dataField="original_series.keyword" |
59 | | - aggregationSize={100} |
60 | | - URLParams |
61 | | - react={{ |
62 | | - and: ['SearchBox'], |
63 | | - }} |
64 | | - /> |
65 | | - </div> |
| 110 | + <div |
| 111 | + className={isClicked ? 'result-container-optional' : 'result-container'} |
| 112 | + > |
| 113 | + <SelectedFilters |
| 114 | + showClearAll |
| 115 | + clearAllLabel="Clear filters" |
| 116 | + className="selected-filters" |
| 117 | + /> |
| 118 | + <ReactiveList |
| 119 | + className="right-col" |
| 120 | + componentId="results" |
| 121 | + dataField="name" |
| 122 | + size={12} |
| 123 | + render={({ data }) => ( |
| 124 | + <ReactiveList.ResultCardsWrapper style={{ margin: '8px 0 0' }}> |
| 125 | + {data.map(item => ( |
| 126 | + <div |
| 127 | + style={{ marginRight: '15px' }} |
| 128 | + className="main-description" |
| 129 | + > |
| 130 | + <div className="ih-item square effect6 top_to_bottom"> |
| 131 | + <a |
| 132 | + target="#" |
| 133 | + href={`https://www.google.com/search?q='${item.original_title}`} |
| 134 | + > |
| 135 | + <div className="img"> |
| 136 | + <img |
| 137 | + src={item.poster_path} |
| 138 | + alt={item.original_title} |
| 139 | + className="result-image" |
| 140 | + /> |
| 141 | + </div> |
| 142 | + <div className="info colored"> |
| 143 | + <h3 |
| 144 | + className="overlay-title" |
| 145 | + dangerouslySetInnerHTML={{ |
| 146 | + __html: item.original_title, |
| 147 | + }} |
| 148 | + /> |
| 149 | + |
| 150 | + <div className="overlay-description"> |
| 151 | + {item.overview} |
| 152 | + </div> |
66 | 153 |
|
67 | | - <div className="col"> |
68 | | - <SelectedFilters /> |
69 | | - <ReactiveList |
70 | | - componentId="SearchResult" |
71 | | - dataField="original_title" |
72 | | - className="result-list-container" |
73 | | - URLParams |
74 | | - from={0} |
75 | | - size={5} |
76 | | - // eslint-disable-next-line react/jsx-no-bind |
77 | | - renderItem={booksReactiveList} |
78 | | - react={{ |
79 | | - and: ['BookSensor', 'SearchBox'], |
80 | | - }} |
81 | | - pagination |
82 | | - /> |
| 154 | + <div className="overlay-info"> |
| 155 | + <div className="rating-time-score-container"> |
| 156 | + <div className="sub-title Rating-data"> |
| 157 | + <b> |
| 158 | + Ratings |
| 159 | + <span className="details"> |
| 160 | + {' '} |
| 161 | + {item.vote_average} |
| 162 | + </span> |
| 163 | + </b> |
| 164 | + </div> |
| 165 | + <div className="time-data"> |
| 166 | + <b> |
| 167 | + <span className="time"> |
| 168 | + <i className="fa fa-clock-o" />{' '} |
| 169 | + </span>{' '} |
| 170 | + <span className="details"> |
| 171 | + {item.release_date} |
| 172 | + </span> |
| 173 | + </b> |
| 174 | + </div> |
| 175 | + <div className="sub-title Score-data"> |
| 176 | + <b> |
| 177 | + Popularity: |
| 178 | + <span className="details"> |
| 179 | + {' '} |
| 180 | + {item.popularity} |
| 181 | + </span> |
| 182 | + </b> |
| 183 | + </div> |
| 184 | + </div> |
| 185 | + <div className="vote-average-lang-container"> |
| 186 | + <div className="sub-title language-data"> |
| 187 | + <b> |
| 188 | + Language: |
| 189 | + <span className="details"> |
| 190 | + {' '} |
| 191 | + { |
| 192 | + item.original_language |
| 193 | + } |
| 194 | + </span> |
| 195 | + </b> |
| 196 | + </div> |
| 197 | + </div> |
| 198 | + </div> |
| 199 | + </div> |
| 200 | + </a> |
| 201 | + </div> |
| 202 | + </div> |
| 203 | + ))} |
| 204 | + </ReactiveList.ResultCardsWrapper> |
| 205 | + )} |
| 206 | + URLParams |
| 207 | + react={{ |
| 208 | + and: ['SearchSensor', 'VoteAverage', 'GenresList'], |
| 209 | + }} |
| 210 | + innerClass={{ |
| 211 | + resultStats: 'result-stats', |
| 212 | + list: 'list', |
| 213 | + listItem: 'list-item', |
| 214 | + image: 'image', |
| 215 | + }} |
| 216 | + /> |
| 217 | + </div> |
| 218 | + </div> |
83 | 219 | </div> |
84 | | - </div> |
85 | | - </ReactiveBase> |
| 220 | + </ReactiveBase> |
| 221 | + <button className="toggle-button" onClick={handleClick}> |
| 222 | + {message} |
| 223 | + </button> |
| 224 | + </div> |
86 | 225 | ); |
87 | | -}; |
88 | | -export async function getServerSideProps(context) { |
89 | | - const initialState = await getServerState(Main, context.resolvedUrl); |
| 226 | +} |
| 227 | +export const getServerSideProps = async (context) => { |
| 228 | + let initialState = {}; |
| 229 | + initialState = await getServerState(Main, context.resolvedUrl); |
90 | 230 | return { |
91 | 231 | props: { initialState }, |
92 | 232 | // will be passed to the page component as props |
93 | 233 | }; |
94 | | -} |
| 234 | +}; |
| 235 | + |
| 236 | +Main.propTypes = { |
| 237 | + // eslint-disable-next-line react/forbid-prop-types |
| 238 | + initialState: PropTypes.object, |
| 239 | + contextCollector: PropTypes.func, |
| 240 | +}; |
95 | 241 |
|
96 | 242 | export default Main; |
0 commit comments