diff --git a/Gemfile b/Gemfile index e896abc5..ce4cc4ac 100644 --- a/Gemfile +++ b/Gemfile @@ -134,6 +134,9 @@ gem 'airbrake' # select2 is beautiful gem 'select2-rails' +# Typeahead +gem 'twitter-typeahead-rails' + group :production do gem 'mysql2' # Database end diff --git a/Gemfile.lock b/Gemfile.lock index f2b6740f..6b9188dd 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -253,6 +253,10 @@ GEM ttfunk (1.4.0) turbolinks (2.5.3) coffee-rails + twitter-typeahead-rails (0.10.5) + actionpack (>= 3.1) + jquery-rails + railties (>= 3.1) tzinfo (1.2.2) thread_safe (~> 0.1) uglifier (2.7.1) @@ -319,6 +323,7 @@ DEPENDENCIES sqlite3 therubyracer turbolinks + twitter-typeahead-rails uglifier (>= 1.3.0) webmock whenever diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js index 7e237364..abbe2c87 100644 --- a/app/assets/javascripts/application.js +++ b/app/assets/javascripts/application.js @@ -15,4 +15,5 @@ //= require turbolinks //= require ckeditor-jquery //= require select2 +//= require twitter/typeahead.min //= require_tree . diff --git a/app/assets/stylesheets/typeahead.css b/app/assets/stylesheets/typeahead.css new file mode 100644 index 00000000..fde250d6 --- /dev/null +++ b/app/assets/stylesheets/typeahead.css @@ -0,0 +1,189 @@ +/* + * typehead.js-bootstrap3.less + * @version 0.2.3 + * https://github.com/hyspace/typeahead.js-bootstrap3.less + * + * Licensed under the MIT license: + * http://www.opensource.org/licenses/MIT + */ +.has-warning .twitter-typeahead .tt-input, +.has-warning .twitter-typeahead .tt-hint { + border-color: #8a6d3b; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); +} +.has-warning .twitter-typeahead .tt-input:focus, +.has-warning .twitter-typeahead .tt-hint:focus { + border-color: #66512c; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #c0a16b; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #c0a16b; +} +.has-error .twitter-typeahead .tt-input, +.has-error .twitter-typeahead .tt-hint { + border-color: #a94442; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); +} +.has-error .twitter-typeahead .tt-input:focus, +.has-error .twitter-typeahead .tt-hint:focus { + border-color: #843534; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ce8483; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ce8483; +} +.has-success .twitter-typeahead .tt-input, +.has-success .twitter-typeahead .tt-hint { + border-color: #3c763d; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); +} +.has-success .twitter-typeahead .tt-input:focus, +.has-success .twitter-typeahead .tt-hint:focus { + border-color: #2b542c; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #67b168; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #67b168; +} +.input-group .twitter-typeahead:first-child .tt-input, +.input-group .twitter-typeahead:first-child .tt-hint { + border-bottom-left-radius: 4px; + border-top-left-radius: 4px; +} +.input-group .twitter-typeahead:last-child .tt-input, +.input-group .twitter-typeahead:last-child .tt-hint { + border-bottom-right-radius: 4px; + border-top-right-radius: 4px; +} +.input-group.input-group-sm .twitter-typeahead .tt-input, +.input-group.input-group-sm .twitter-typeahead .tt-hint { + height: 30px; + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +select.input-group.input-group-sm .twitter-typeahead .tt-input, +select.input-group.input-group-sm .twitter-typeahead .tt-hint { + height: 30px; + line-height: 30px; +} +textarea.input-group.input-group-sm .twitter-typeahead .tt-input, +textarea.input-group.input-group-sm .twitter-typeahead .tt-hint, +select[multiple].input-group.input-group-sm .twitter-typeahead .tt-input, +select[multiple].input-group.input-group-sm .twitter-typeahead .tt-hint { + height: auto; +} +.input-group.input-group-sm .twitter-typeahead:not(:first-child):not(:last-child) .tt-input, +.input-group.input-group-sm .twitter-typeahead:not(:first-child):not(:last-child) .tt-hint { + border-radius: 0; +} +.input-group.input-group-sm .twitter-typeahead:first-child .tt-input, +.input-group.input-group-sm .twitter-typeahead:first-child .tt-hint { + border-bottom-left-radius: 3px; + border-top-left-radius: 3px; + border-bottom-right-radius: 0; + border-top-right-radius: 0; +} +.input-group.input-group-sm .twitter-typeahead:last-child .tt-input, +.input-group.input-group-sm .twitter-typeahead:last-child .tt-hint { + border-bottom-left-radius: 0; + border-top-left-radius: 0; + border-bottom-right-radius: 3px; + border-top-right-radius: 3px; +} +.input-group.input-group-lg .twitter-typeahead .tt-input, +.input-group.input-group-lg .twitter-typeahead .tt-hint { + height: 46px; + padding: 10px 16px; + font-size: 18px; + line-height: 1.33; + border-radius: 6px; +} +select.input-group.input-group-lg .twitter-typeahead .tt-input, +select.input-group.input-group-lg .twitter-typeahead .tt-hint { + height: 46px; + line-height: 46px; +} +textarea.input-group.input-group-lg .twitter-typeahead .tt-input, +textarea.input-group.input-group-lg .twitter-typeahead .tt-hint, +select[multiple].input-group.input-group-lg .twitter-typeahead .tt-input, +select[multiple].input-group.input-group-lg .twitter-typeahead .tt-hint { + height: auto; +} +.input-group.input-group-lg .twitter-typeahead:not(:first-child):not(:last-child) .tt-input, +.input-group.input-group-lg .twitter-typeahead:not(:first-child):not(:last-child) .tt-hint { + border-radius: 0; +} +.input-group.input-group-lg .twitter-typeahead:first-child .tt-input, +.input-group.input-group-lg .twitter-typeahead:first-child .tt-hint { + border-bottom-left-radius: 6px; + border-top-left-radius: 6px; + border-bottom-right-radius: 0; + border-top-right-radius: 0; +} +.input-group.input-group-lg .twitter-typeahead:last-child .tt-input, +.input-group.input-group-lg .twitter-typeahead:last-child .tt-hint { + border-bottom-left-radius: 0; + border-top-left-radius: 0; + border-bottom-right-radius: 6px; + border-top-right-radius: 6px; +} +.twitter-typeahead { + width: 100%; +} +.input-group .twitter-typeahead { + display: table-cell !important; + float: left; +} +.twitter-typeahead .tt-hint { + color: #999999; +} +.twitter-typeahead .tt-input { + z-index: 2; +} +.twitter-typeahead .tt-input[disabled], +.twitter-typeahead .tt-input[readonly], +fieldset[disabled] .twitter-typeahead .tt-input { + cursor: not-allowed; + background-color: #eeeeee !important; +} +.tt-dropdown-menu { + position: absolute; + top: 100%; + left: 0; + z-index: 1000; + min-width: 160px; + width: 100%; + padding: 5px 0; + margin: 2px 0 0; + list-style: none; + font-size: 14px; + background-color: #ffffff; + border: 1px solid #cccccc; + border: 1px solid rgba(0, 0, 0, 0.15); + border-radius: 4px; + -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175); + box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175); + background-clip: padding-box; + *border-right-width: 2px; + *border-bottom-width: 2px; +} +.tt-dropdown-menu .tt-suggestion { + display: block; + padding: 3px 20px; + clear: both; + font-weight: normal; + line-height: 1.42857143; + color: #333333; + white-space: nowrap; +} +.tt-dropdown-menu .tt-suggestion.tt-cursor { + text-decoration: none; + outline: 0; + background-color: #f5f5f5; + color: #262626; +} +.tt-dropdown-menu .tt-suggestion.tt-cursor a { + color: #262626; +} +.tt-dropdown-menu .tt-suggestion p { + margin: 0; +} diff --git a/app/controllers/events_controller.rb b/app/controllers/events_controller.rb index 2f0cb25a..0cf4dbb2 100644 --- a/app/controllers/events_controller.rb +++ b/app/controllers/events_controller.rb @@ -90,30 +90,23 @@ def scan authorize! :update, @event end - def check_in + def scan_barcode @event = Event.find params.require(:id) authorize! :update, @event barcode = params.require(:code) + @registration = @event.registrations.find_by barcode: barcode + check_in + end - @registration = @event.registrations.find_by_barcode barcode - - if @registration - if not @registration.is_paid - flash.now[:warning] = "Person has not paid yet! Resting amount: €" + @registration.to_pay.to_s - elsif @registration.checked_in_at - flash.now[:warning] = "Person already checked in at " + view_context.nice_time(@registration.checked_in_at) + "!" - else - flash.now[:success] = "Person has been scanned!" - @registration.checked_in_at = Time.now - @registration.save! - end - else - flash.now[:error] = "Barcode not found" - end - - render action: :scan + def scan_username + @event = Event.find params.require(:id) + authorize! :update, @event + username = params.require(:username) + @registration = @event.registrations.find_by name: username + check_in end + def export_status @event = Event.find params.require(:id) authorize! :read, @event @@ -132,4 +125,31 @@ def generate_export @event.generate_xls end + def list_registrations + @event = Event.find params.require(:id) + authorize! :read, @event + render json: @event.registrations + end + + private + def check_in + + if @registration + if not @registration.is_paid + flash.now[:warning] = + "Person has not paid yet! Resting amount: €" + @registration.to_pay.to_s + elsif @registration.checked_in_at + flash.now[:warning] = "Person already checked in at " + + view_context.nice_time(@registration.checked_in_at) + "!" + else + flash.now[:success] = "Person has been scanned!" + @registration.checked_in_at = Time.now + @registration.save! + end + else + flash.now[:error] = "Registration not found" + end + render action: :scan + end + end diff --git a/app/views/events/scan.html.erb b/app/views/events/scan.html.erb index 53d05e27..bba6a832 100644 --- a/app/views/events/scan.html.erb +++ b/app/views/events/scan.html.erb @@ -27,18 +27,62 @@
- <%= form_tag check_in_event_path(@event), - url: scan_event_path(@event), - remote: false do %> -
- - + <%= form_tag scan_barcode_event_path(@event), remote: false do %> +
+
+ + + + +
+ <% end %> + +
- + <%= form_tag scan_username_event_path(@event), remote: false do %> +
+
+ + + + +
+
<% end %> +
+
+ + diff --git a/config/routes.rb b/config/routes.rb index 22935945..66132e67 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -47,7 +47,9 @@ member do get 'statistics' get 'scan' - post 'check_in' + get 'list_registrations' + post 'scan_barcode' + post 'scan_username' end resources :periods