Skip to content

Commit

Permalink
Filter Seats based on their Price
Browse files Browse the repository at this point in the history
For comparison [see this commit][commit]

Nothing exciting here. The ergonomics is similar to the Stimulus version.

[commit]: seanpdoyle@752ef6d
  • Loading branch information
jho406 committed Oct 8, 2023
1 parent 6eda487 commit a01f87f
Show file tree
Hide file tree
Showing 10 changed files with 150 additions and 1 deletion.
1 change: 1 addition & 0 deletions app/assets/images/icons/check-circle.svg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions app/assets/images/icons/circle.svg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
55 changes: 55 additions & 0 deletions app/components/SeatFilter.js
@@ -0,0 +1,55 @@
import React from 'react'
import SVG from 'react-inlinesvg';
import uncheckedSvg from '../assets/images/icons/circle.svg'
import checkedSvg from '../assets/images/icons/check-circle.svg'

const MaxRadioButton = (props) => {
const { label, ...rest} = props

return (
<>
<input
{...rest}
className="syos-tile-controls__input"
ref={React.createRef()}
/>
<label className="syos-tile-controls__control" htmlFor={rest.id}>
<SVG src={ uncheckedSvg } className="syos-icon syos-tile-controls__icon syos-tile-controls__icon--unselected" aria-hidden={true}/>
<SVG src={ checkedSvg } className="syos-icon syos-tile-controls__icon syos-tile-controls__icon--selected" aria-hidden={true}/>
{ label }
</label>
</>
)
}

export default class extends React.Component {
render () {
const {
filterForm,
} = this.props

const controlElements = Object
.values(filterForm.inputs)
.map((inputProps) => <MaxRadioButton {...inputProps} />);

return (
<form {...filterForm.props}>
<fieldset className="syos-u-margin-bottom-6">
<legend className="syos-u-margin-bottom-2 syos-inline-stack">
<h2 className="syos-inline-stack__item">
Filter by max price
</h2>

<input className="syos-button syos-button--transparent" type="reset" value="Clear Filters" />
</legend>

<div className="syos-tile-controls">
{controlElements}
</div>

<input type="submit" className="syos-button syos-u-margin-top-2" value="Apply Filters" />
</fieldset>
</form>
)
}
}
10 changes: 9 additions & 1 deletion app/components/SeatingMap.js
Expand Up @@ -18,7 +18,15 @@ const buildSectionElements = (sections) => {
</a>
))

return <g key={index}>{seatElements}</g>
return (
<g
key={index}
opacity={section.opacity}
aria-hidden={section.hidden}
>
{seatElements}
</g>
)
})
}

Expand Down
14 changes: 14 additions & 0 deletions app/views/seats/_filters.json.props
@@ -0,0 +1,14 @@
json.filter_form do
form_props(
url: venue_floor_seats_path(venue, floor),
method: :get
) do |f|
[5_00, 10_00, 15_00, nil].each_cons(2).to_a.each do |max_nmax|
maximum = max_nmax[0]
next_maximum = max_nmax[1]
checked = params[:maximum].to_i == maximum || [params[:maximum], next_maximum].none?

f.radio_button(:maximum, maximum, checked: checked, label: number_to_currency(maximum / 100.0))
end
end
end
8 changes: 8 additions & 0 deletions app/views/seats/_sections.json.props
@@ -1,4 +1,12 @@
json.array! sections do |section|
if params.fetch(:maximum, Float::INFINITY).to_f >= section.price
json.opacity "1.0"
json.hidden false
else
json.opacity "0.3"
json.hidden true
end

json.seats do
json.array! section.seats do |seat|
json.x seat.x
Expand Down
3 changes: 3 additions & 0 deletions app/views/seats/index.js
@@ -1,5 +1,6 @@
import React from 'react'
import SeatDialog from '../../components/SeatDialog'
import SeatFilter from '../../components/SeatFilter'
import Cart from '../../components/Cart'
import SeatingMap from '../../components/SeatingMap'
import SeatingLegend from '../../components/SeatingLegend'
Expand All @@ -13,6 +14,7 @@ export default (props) => {
cart,
seat,
floors,
filters,
} = props

return (
Expand All @@ -34,6 +36,7 @@ export default (props) => {
<SeatingMap sections={sections} />
</div>
<div className="syos-frame__sidebar">
<SeatFilter {...filters} />
<Cart cart={cart} />
</div>
</section>
Expand Down
3 changes: 3 additions & 0 deletions app/views/seats/index.json.props
Expand Up @@ -9,6 +9,9 @@ end
json.cart(partial: ['cart', locals: local_assigns]) do
end

json.filters(partial: ['filters', locals: local_assigns]) do
end

json.seat do
json.show false
end
3 changes: 3 additions & 0 deletions app/views/seats/show.json.props
Expand Up @@ -9,6 +9,9 @@ end
json.cart(partial: ['cart', locals: local_assigns]) do
end

json.filters(partial: ['filters', locals: local_assigns]) do
end

json.seat do
json.show true
json.section_name seat.section.name
Expand Down
53 changes: 53 additions & 0 deletions test/controllers/seats_controller_test.rb
Expand Up @@ -21,4 +21,57 @@ class SeatsControllerTest < ActionDispatch::IntegrationTest

assert_equal Cart.last.token, cookies[:cart_token]
end

test "#index when including sections when filtering by price" do
maximum = 10_00
price = maximum
venue = create(:benedum_center)
floor = create(:orchestra, venue: venue)
section = create(:section, floor: floor, price: price)
create(:seat, section: section)

get venue_floor_seats_path(venue, floor, maximum: maximum, format: :json)

json = JSON.parse(body)
assert_equal json["data"]["sections"][0]["opacity"], "1.0"
assert_equal json["data"]["sections"][0]["hidden"], false
end

test "#index when excluding sections when filtering by price" do
maximum = 5_00
price = 10_00
venue = create(:benedum_center)
floor = create(:orchestra, venue: venue)
section = create(:section, floor: floor, price: price)
create(:seat, section: section)

get venue_floor_seats_path(venue, floor, maximum: maximum, format: :json)

json = JSON.parse(body)
assert_equal json["data"]["sections"][0]["opacity"], "0.3"
assert_equal json["data"]["sections"][0]["hidden"], true
end

test "#index with a ?maximum query parameter" do
venue = create(:benedum_center)
floor = create(:orchestra, venue: venue)
maximum = 10_00

get venue_floor_seats_path(venue, floor, maximum: maximum, format: :json)

json = JSON.parse(body)
assert_equal json["data"]["filters"]["controls"][1]["maximum"], maximum
assert_equal json["data"]["filters"]["controls"][1]["isChecked"], true
end

test "#index without a ?maximum query parameter" do
venue = create(:benedum_center)
floor = create(:orchestra, venue: venue)

get venue_floor_seats_path(venue, floor, format: :json)

json = JSON.parse(body)
assert_equal json["data"]["filters"]["controls"][2]["maximum"], 1500
assert_equal json["data"]["filters"]["controls"][2]["isChecked"], true
end
end

0 comments on commit a01f87f

Please sign in to comment.