Merge remote-tracking branch 'github/master'
# Conflicts: # composer.lock
This commit is contained in:
commit
beab5d64a5
|
|
@ -0,0 +1,114 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests;
|
||||
use App\Models\Attendee;
|
||||
use App\Models\Event;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Http\Request;
|
||||
use JavaScript;
|
||||
|
||||
class EventQrcodeCheckInController extends Controller
|
||||
{
|
||||
/**
|
||||
* Show the check-in page
|
||||
*
|
||||
* @param $event_id
|
||||
* @return \Illuminate\View\View
|
||||
*/
|
||||
public function showCheckIn($event_id)
|
||||
{
|
||||
$event = Event::scope()->findOrFail($event_id);
|
||||
|
||||
JavaScript::put([
|
||||
'qrcodeCheckInRoute' => route('postQRCodeCheckInAttendee', ['event_id' => $event->id])
|
||||
]);
|
||||
|
||||
return view('ManageEvent.QrcodeCheckIn', compact('event'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check in an attendee
|
||||
*
|
||||
* @param $event_id
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function postCheckInAttendee($event_id, Request $request)
|
||||
{
|
||||
$event = Event::scope()->findOrFail($event_id);
|
||||
|
||||
$qrcodeToken = $request->get('qrcode_token');
|
||||
|
||||
$attendee = Attendee::scope()->withoutCancelled()
|
||||
->join('tickets', 'tickets.id', '=', 'attendees.ticket_id')
|
||||
->where(function ($query) use ($event, $qrcodeToken) {
|
||||
$query->where('attendees.event_id', $event->id)
|
||||
->where('attendees.private_reference_number', $qrcodeToken);
|
||||
})->select([
|
||||
'attendees.id',
|
||||
'attendees.order_id',
|
||||
'attendees.first_name',
|
||||
'attendees.last_name',
|
||||
'attendees.email',
|
||||
'attendees.reference',
|
||||
'attendees.arrival_time',
|
||||
'attendees.has_arrived',
|
||||
'tickets.title as ticket',
|
||||
])->first();
|
||||
|
||||
if(is_null($attendee)){
|
||||
return response()->json(['status' => 'error', 'message' => "Invalid Ticket! Please try again."]);
|
||||
}
|
||||
|
||||
$relatedAttendesCount = Attendee::where('id', '!=', $attendee->id)
|
||||
->where([
|
||||
'order_id' => $attendee->order_id,
|
||||
'has_arrived' => false
|
||||
])->count();
|
||||
|
||||
if($relatedAttendesCount >= 1){
|
||||
$confirmOrderTicketsRoute = route('confirmCheckInOrderTickets', [$event->id, $attendee->order_id]);
|
||||
|
||||
$appendedText = '<br><br><form action="'. $confirmOrderTicketsRoute .'" method="POST">'. csrf_field() .'<input type="hidden" name="_method" value="PUT"><div class="row"><div class="col-md-10 col-md-offset-1 col-xs-12"><button class="btn btn-primary btn-block btn-lg" type="submit"><i class="fa fa-ticket"></i> Check in other tickets associated to this order</button></div></div></form>';
|
||||
} else {
|
||||
$appendedText = '';
|
||||
}
|
||||
|
||||
if ($attendee->has_arrived) {
|
||||
return response()->json([
|
||||
'status' => 'error',
|
||||
'message' => 'Warning: This attendee has already been checked in at '. $attendee->arrival_time->format('H:i A, F j'). '.' . $appendedText
|
||||
]);
|
||||
}
|
||||
|
||||
Attendee::find($attendee->id)->update(['has_arrived' => true, 'arrival_time' => Carbon::now()]);
|
||||
|
||||
return response()->json([
|
||||
'status' => 'success',
|
||||
'message' => 'Success !<br>Name: ' . $attendee->first_name . ' ' . $attendee->last_name . '<br>Reference: '. $attendee->reference . '<br>Ticket: '. $attendee->ticket . '.' . $appendedText
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Confirm tickets of same order.
|
||||
*
|
||||
* @param $event_id
|
||||
* @param $order_id
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function confirmOrderTickets($event_id, $order_id)
|
||||
{
|
||||
$updateRowsCount = Attendee::where([
|
||||
'event_id' => $event_id,
|
||||
'order_id' => $order_id,
|
||||
'has_arrived' => false
|
||||
])
|
||||
->update(['has_arrived' => true, 'arrival_time' => Carbon::now()]);
|
||||
|
||||
session()->flash('success_message', $updateRowsCount . ' other tickets checked in.');
|
||||
return back();
|
||||
}
|
||||
}
|
||||
|
|
@ -562,6 +562,27 @@ Route::group(['middleware' => ['auth', 'first.run']], function () {
|
|||
'uses' => 'EventCheckInController@postCheckInAttendee',
|
||||
]);
|
||||
|
||||
|
||||
/*
|
||||
* -------
|
||||
* QRCode Check In App
|
||||
* -------
|
||||
*/
|
||||
Route::get('{event_id}/qrcode_check_in', [
|
||||
'as' => 'showQRCodeChechIn',
|
||||
'uses' => 'EventQrcodeCheckInController@showCheckIn',
|
||||
]);
|
||||
|
||||
Route::post('{event_id}/qrcode_check_in', [
|
||||
'as' => 'postQRCodeCheckInAttendee',
|
||||
'uses' => 'EventQrcodeCheckInController@postCheckInAttendee',
|
||||
]);
|
||||
|
||||
Route::match(['PUT', 'PATCH'], '{event_id}/confirm_order_tickets/{order_id}', [
|
||||
'as' => 'confirmCheckInOrderTickets',
|
||||
'uses' => 'EventQrcodeCheckInController@confirmOrderTickets',
|
||||
]);
|
||||
|
||||
/*
|
||||
* -------
|
||||
* Promote
|
||||
|
|
|
|||
|
|
@ -32,6 +32,8 @@ class Attendee extends MyBaseModel
|
|||
'ticket_id',
|
||||
'account_id',
|
||||
'reference',
|
||||
'has_arrived',
|
||||
'arrival_time'
|
||||
];
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -25,7 +25,8 @@
|
|||
"omnipay/paypal": "*",
|
||||
"omnipay/bitpay": "dev-master",
|
||||
"omnipay/coinbase": "dev-master",
|
||||
"barryvdh/laravel-ide-helper": "^2.1"
|
||||
"barryvdh/laravel-ide-helper": "^2.1",
|
||||
"laracasts/utilities": "^2.1"
|
||||
|
||||
},
|
||||
"require-dev": {
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -167,6 +167,7 @@ return [
|
|||
Mews\Purifier\PurifierServiceProvider::class,
|
||||
MaxHoffmann\Parsedown\ParsedownServiceProvider::class,
|
||||
Barryvdh\LaravelIdeHelper\IdeHelperServiceProvider::class,
|
||||
Laracasts\Utilities\JavaScript\JavaScriptServiceProvider::class,
|
||||
],
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| View to Bind JavaScript Vars To
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Set this value to the name of the view (or partial) that
|
||||
| you want to prepend all JavaScript variables to.
|
||||
| This can be a single view, or an array of views.
|
||||
| Example: 'footer' or ['footer', 'bottom']
|
||||
|
|
||||
*/
|
||||
'bind_js_vars_to_this_view' => ['Shared.Layouts.ViewJavascript'],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| JavaScript Namespace
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| By default, we'll add variables to the global window object. However,
|
||||
| it's recommended that you change this to some namespace - anything.
|
||||
| That way, you can access vars, like "SomeNamespace.someVariable."
|
||||
|
|
||||
*/
|
||||
'js_namespace' => 'Attendize'
|
||||
|
||||
];
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 7.1 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 2.2 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 3.0 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 9.2 KiB |
|
|
@ -0,0 +1,99 @@
|
|||
body{
|
||||
font-family: "Source Sans Pro", sans-serif;
|
||||
}
|
||||
|
||||
a:active, a:focus, a:visited{
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:hover{
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
#outdiv
|
||||
{
|
||||
width: 400px;
|
||||
height: 250px;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
#v{
|
||||
width: 400px;
|
||||
height: auto;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: 2px solid #c5c5c5;
|
||||
}
|
||||
|
||||
#qrfile{
|
||||
border: 2px solid #c5c5c5;
|
||||
width: 400px;
|
||||
height: 250px;
|
||||
}
|
||||
|
||||
#qr-canvas{
|
||||
display:none;
|
||||
}
|
||||
|
||||
#help-text{
|
||||
z-index: 9999999999;
|
||||
position: relative;
|
||||
color: #00AEFB;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
#imghelp{
|
||||
position:relative;
|
||||
left:0px;
|
||||
top:-160px;
|
||||
z-index:100;
|
||||
background:#f2f2f2;
|
||||
margin-left:35px;
|
||||
margin-right:35px;
|
||||
padding-top:15px;
|
||||
padding-bottom:15px;
|
||||
border-radius:20px;
|
||||
}
|
||||
|
||||
.selector{
|
||||
cursor:pointer;
|
||||
}
|
||||
|
||||
#result{
|
||||
border: 1px solid #eaeaea;
|
||||
padding: 10px;
|
||||
margin-top: 3em;
|
||||
color: #456D86;
|
||||
width: 50%;
|
||||
background-color: #f2f2f2;
|
||||
font-size: 1.5em;
|
||||
font-weight: 500;
|
||||
box-shadow: none;
|
||||
border-radius: 3px;
|
||||
transition: background 0.4s ease-in-out;
|
||||
}
|
||||
|
||||
/* Mobile */
|
||||
@media only screen and (max-width: 480px) {
|
||||
#result{
|
||||
width: 90%;
|
||||
}
|
||||
|
||||
#outdiv{
|
||||
width: 300px;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
#help-text{
|
||||
top: -35px;
|
||||
}
|
||||
|
||||
#qrfile{
|
||||
width: 300px;
|
||||
}
|
||||
|
||||
#v{
|
||||
width: 300px;
|
||||
}
|
||||
}
|
||||
Binary file not shown.
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1,153 @@
|
|||
// QRCODE reader Copyright 2011 Lazar Laszlo
|
||||
// http://www.webqr.com
|
||||
|
||||
var workingAway = false;
|
||||
var gCtx = null;
|
||||
var gCanvas = null;
|
||||
var c=0;
|
||||
var stype=0;
|
||||
var gUM=false;
|
||||
var webkit=false;
|
||||
var moz=false;
|
||||
var v=null;
|
||||
|
||||
var beepSound = new Audio('/mp3/beep.mp3');
|
||||
|
||||
var vidhtml = '<video id="v" autoplay></video>';
|
||||
|
||||
function initCanvas(w,h)
|
||||
{
|
||||
gCanvas = document.getElementById("qr-canvas");
|
||||
gCanvas.style.width = w + "px";
|
||||
gCanvas.style.height = h + "px";
|
||||
gCanvas.width = w;
|
||||
gCanvas.height = h;
|
||||
gCtx = gCanvas.getContext("2d");
|
||||
gCtx.clearRect(0, 0, w, h);
|
||||
}
|
||||
|
||||
|
||||
function captureToCanvas() {
|
||||
if(stype!=1)
|
||||
return;
|
||||
if(gUM)
|
||||
{
|
||||
try{
|
||||
gCtx.drawImage(v,0,0);
|
||||
try{
|
||||
qrcode.decode();
|
||||
}
|
||||
catch(e){
|
||||
console.log(e);
|
||||
setTimeout(captureToCanvas, 500);
|
||||
};
|
||||
}
|
||||
catch(e){
|
||||
console.log(e);
|
||||
setTimeout(captureToCanvas, 500);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
function htmlEntities(str) {
|
||||
return String(str).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"');
|
||||
}
|
||||
|
||||
function read(qrcode_token)
|
||||
{
|
||||
if(workingAway) {
|
||||
return;
|
||||
}
|
||||
|
||||
workingAway = true;
|
||||
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: Attendize.qrcodeCheckInRoute,
|
||||
data: {qrcode_token: htmlEntities(qrcode_token)},
|
||||
cache: false,
|
||||
complete: function(){
|
||||
beepSound.play();
|
||||
},
|
||||
error: function() {
|
||||
},
|
||||
success: function(response) {
|
||||
document.getElementById("result").innerHTML = "<b>" + response.message +"</b>";
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function isCanvasSupported(){
|
||||
var elem = document.createElement('canvas');
|
||||
return !!(elem.getContext && elem.getContext('2d'));
|
||||
}
|
||||
|
||||
function success(stream) {
|
||||
if(webkit)
|
||||
v.src = window.webkitURL.createObjectURL(stream);
|
||||
else
|
||||
if(moz)
|
||||
{
|
||||
v.mozSrcObject = stream;
|
||||
v.play();
|
||||
}
|
||||
else
|
||||
v.src = stream;
|
||||
gUM=true;
|
||||
setTimeout(captureToCanvas, 500);
|
||||
}
|
||||
|
||||
function error(error) {
|
||||
gUM=false;
|
||||
return;
|
||||
}
|
||||
|
||||
function load()
|
||||
{
|
||||
if(isCanvasSupported() && window.File && window.FileReader)
|
||||
{
|
||||
initCanvas(800, 600);
|
||||
qrcode.callback = read;
|
||||
document.getElementById("mainbody").style.display="inline";
|
||||
setwebcam();
|
||||
}
|
||||
else
|
||||
{
|
||||
document.getElementById("mainbody").style.display="inline";
|
||||
document.getElementById("mainbody").innerHTML='<p id="mp1">Attendize Checkpoint Manager for HTML5 capable browsers</p><br>'+
|
||||
'<br><p id="mp2">sorry your browser is not supported</p><br><br>'+
|
||||
'<p id="mp1">try <a href="http://www.mozilla.com/firefox"><img src="/assets/images/firefox.png"/></a> or <a href="http://chrome.google.com"><img src="/assets/images/chrome_logo.gif"/></a> or <a href="http://www.opera.com"><img src="/assets/images/Opera-logo.png"/></a></p>';
|
||||
}
|
||||
}
|
||||
|
||||
function setwebcam()
|
||||
{
|
||||
document.getElementById("help-text").style.display = "block";
|
||||
document.getElementById("result").innerHTML='Scanning <i class="fa fa-spinner fa-spin"></i>';
|
||||
if(stype==1)
|
||||
{
|
||||
setTimeout(captureToCanvas, 500);
|
||||
return;
|
||||
}
|
||||
var n=navigator;
|
||||
document.getElementById("outdiv").innerHTML = vidhtml;
|
||||
v=document.getElementById("v");
|
||||
|
||||
if(n.getUserMedia)
|
||||
n.getUserMedia({video: true, audio: false}, success, error);
|
||||
else
|
||||
if(n.webkitGetUserMedia)
|
||||
{
|
||||
webkit=true;
|
||||
n.webkitGetUserMedia({video:true, audio: false}, success, error);
|
||||
}
|
||||
else
|
||||
if(n.mozGetUserMedia)
|
||||
{
|
||||
moz=true;
|
||||
n.mozGetUserMedia({video: true, audio: false}, success, error);
|
||||
}
|
||||
|
||||
stype=1;
|
||||
setTimeout(captureToCanvas, 500);
|
||||
}
|
||||
|
|
@ -0,0 +1,97 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>
|
||||
Attendize QRCode Check In: {{ $event->title }}
|
||||
</title>
|
||||
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" integrity="sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7" crossorigin="anonymous">
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css">
|
||||
<link href='https://fonts.googleapis.com/css?family=Source+Sans+Pro:400,700' rel='stylesheet' type='text/css'>
|
||||
{!! HTML::style('assets/stylesheet/qrcode-check-in.css') !!}
|
||||
{!! HTML::script('vendor/jquery/jquery.js') !!}
|
||||
|
||||
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0">
|
||||
|
||||
@include('Shared/Layouts/ViewJavascript')
|
||||
|
||||
<!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
|
||||
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
|
||||
<!--[if lt IE 9]>
|
||||
<script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
|
||||
<script src="https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js"></script>
|
||||
<![endif]-->
|
||||
|
||||
<script>
|
||||
$(function() {
|
||||
$.ajaxSetup({
|
||||
headers: {
|
||||
'X-CSRF-Token': "<?php echo csrf_token() ?>"
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
{!! HTML::script('vendor/qrcode-scan/llqrcode.js') !!}
|
||||
{!! HTML::script('vendor/qrcode-scan/webqr.js') !!}
|
||||
</head>
|
||||
<body>
|
||||
<div id="main">
|
||||
<header id="header">
|
||||
<h2 class="text-center"><img style="width: 40px;" class="logo" alt="Attendize" src="{{ asset('/assets/images/logo-100x100-lightBg.png') }}"/><br><span style="font-size: 0.7em;">Check In: <strong>{{ $event->title }}</strong></span></h2>
|
||||
</header>
|
||||
|
||||
<hr>
|
||||
|
||||
@if(session()->has('success_message'))
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-6 col-md-offset-3 col-xs-12">
|
||||
<div class="alert alert-success alert-dismissible text-center" role="alert">
|
||||
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||
<p><strong>Success</strong>: {{ session('success_message') }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<div id="mainbody">
|
||||
<table class="tsel" border="0" width="100%">
|
||||
<tr>
|
||||
<td valign="top" align="center" width="50%">
|
||||
<table class="tsel" border="0">
|
||||
<tr>
|
||||
<td colspan="2" align="center">
|
||||
<div id="outdiv">
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="3" align="center">
|
||||
<p id="help-text">Put the QR code in front of your Camera (Not too close)</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="3" align="center">
|
||||
<p style="position: relative; bottom: -2em;"><a onclick="event.preventDefault(); workingAway = false; load();" href="{{ Request::url() }}"><i class="fa fa-refresh"></i> Scan another ticket</a></p>
|
||||
<div id="result"></div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<footer id="footer">
|
||||
<br>
|
||||
<br>
|
||||
<h5 align="center" style="color: #6D717A;">© <a href="https://www.attendize.com/">Attendize</a> {{ date('Y') }} · All Rights Reserved.</h5>
|
||||
</footer>
|
||||
</div>
|
||||
|
||||
<canvas id="qr-canvas" width="800" height="600"></canvas>
|
||||
<script type="text/javascript">load();</script>
|
||||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js" integrity="sha384-0mSbJDEHialfmuBBQP6A4Qrprq5OVfW37PRR3j5ELqxss1yVqOtnepnHVP9aJ7xS" crossorigin="anonymous"></script>
|
||||
</body>
|
||||
</html>
|
||||
Loading…
Reference in New Issue