fix+add: seats + seat-chooser
This commit is contained in:
parent
2c6745e812
commit
b0cc5b5278
31 changed files with 808 additions and 115 deletions
|
@ -8,6 +8,7 @@ public function __construct()
|
||||||
{
|
{
|
||||||
$this->middleware('auth');
|
$this->middleware('auth');
|
||||||
$this->middleware('atleast:employee');
|
$this->middleware('atleast:employee');
|
||||||
|
$this->middleware('permission:manage_cinemas')->only(['create', 'store', 'edit', 'update', 'destroy']);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function showAllCinemas()
|
public function showAllCinemas()
|
||||||
|
|
|
@ -10,6 +10,7 @@ class GenreController extends Controller
|
||||||
public function __construct() {
|
public function __construct() {
|
||||||
$this->middleware('auth');
|
$this->middleware('auth');
|
||||||
$this->middleware('atleast:employee');
|
$this->middleware('atleast:employee');
|
||||||
|
$this->middleware('permission:manage_genres')->only(['create', 'store', 'edit', 'update', 'destroy']);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function showAllGenres() {
|
public function showAllGenres() {
|
||||||
|
|
|
@ -11,6 +11,7 @@ class MovieController extends Controller
|
||||||
public function __construct() {
|
public function __construct() {
|
||||||
$this->middleware('auth');
|
$this->middleware('auth');
|
||||||
$this->middleware('atleast:employee');
|
$this->middleware('atleast:employee');
|
||||||
|
$this->middleware('permission:manage_movies')->only(['create', 'store', 'edit', 'update', 'destroy']);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function showAllMovies() {
|
public function showAllMovies() {
|
||||||
|
|
|
@ -29,5 +29,10 @@ public function user()
|
||||||
return $this->belongsTo(User::class, 'user_id', 'id');
|
return $this->belongsTo(User::class, 'user_id', 'id');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function string()
|
||||||
|
{
|
||||||
|
return $this->address_street . ", " . $this->address_city . ", " . $this->address_state . " " . $this->address_zip . ", " . $this->address_country;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,4 +43,29 @@ public function cinema()
|
||||||
return $this->belongsTo(Cinema::class, 'cinema_id', 'cinema_id');
|
return $this->belongsTo(Cinema::class, 'cinema_id', 'cinema_id');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function seatMatrix($showing_id = null)
|
||||||
|
{
|
||||||
|
$seats = $this->seats;
|
||||||
|
$matrix = [];
|
||||||
|
// first, create an empty matrix
|
||||||
|
for ($i = 0; $i < $this->room_rows-1; $i++) {
|
||||||
|
$matrix[$i] = [];
|
||||||
|
for ($j = 0; $j < $this->room_columns-1; $j++) {
|
||||||
|
$matrix[$i][$j] = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// then, fill it with the seats
|
||||||
|
foreach ($seats as $seat) {
|
||||||
|
$matrix[$seat->seat_row-1][$seat->seat_column-1] = [
|
||||||
|
'seat_id' => $seat->seat_id,
|
||||||
|
'seat_row' => $seat->seat_row,
|
||||||
|
'seat_column' => $seat->seat_column,
|
||||||
|
'seat_type' => $seat->seat_type,
|
||||||
|
'seat_linked_id' => $seat->seat_linked_id,
|
||||||
|
'reserved' => $showing_id ? $seat->isReserved($showing_id) : false,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
return $matrix;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,8 @@ class Seat extends Model
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
'seat_row',
|
'seat_row',
|
||||||
'seat_number',
|
'seat_number',
|
||||||
'seat_type', // enum('standard', 'wheelchair', 'loveseat')
|
'seat_type', // enum('standard', 'wheelchair', 'loveseat', 'not_available')
|
||||||
|
'seat_linked_id', // if this is a loveseat, this is the other seat
|
||||||
'room_id',
|
'room_id',
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -27,28 +28,27 @@ public function room()
|
||||||
return $this->belongsTo(Room::class, 'room_id', 'room_id');
|
return $this->belongsTo(Room::class, 'room_id', 'room_id');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function orders()
|
|
||||||
{
|
|
||||||
return $this->belongsToMany(Order::class, 'order_seats', 'seat_id', 'order_id');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function tickets()
|
public function tickets()
|
||||||
{
|
{
|
||||||
return $this->hasMany(Ticket::class, 'seat_id', 'seat_id');
|
return $this->hasMany(Ticket::class, 'seat_id', 'seat_id');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function linked_seat()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(Seat::class, 'seat_linked_id', 'seat_id');
|
||||||
|
}
|
||||||
|
|
||||||
// isReserved(int showing_id) method
|
// isReserved(int showing_id) method
|
||||||
// Looks at showing / order / ticket if it's reserved
|
// Looks at showing / order / ticket if it's reserved
|
||||||
// Returns true if it is reserved, false if it isn't
|
// Returns true if it is reserved, false if it isn't
|
||||||
public function is_reserved(int $showing_id)
|
public function isReserved(int $showing_id): bool
|
||||||
{
|
{
|
||||||
$tickets = $this->tickets()->where('showing_id', $showing_id)->get();
|
$tickets = $this->tickets->where('showing_id', $showing_id);
|
||||||
foreach ($tickets as $ticket) {
|
foreach ($tickets as $ticket) {
|
||||||
if ($ticket->order->order_status == 'pending' || $ticket->order->order_status == 'paid') {
|
if ($ticket->showing_id == $showing_id) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Carbon\Carbon;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -45,4 +46,29 @@ public function nowPlaying()
|
||||||
return $this->where('showing_start', '>=', now())->get();
|
return $this->where('showing_start', '>=', now())->get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function end_time() {
|
||||||
|
$date = new Carbon($this->showing_start);
|
||||||
|
$date->addMinutes($this->movie->movie_length);
|
||||||
|
return $date;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function tickets()
|
||||||
|
{
|
||||||
|
return $this->hasMany(Ticket::class, 'showing_id', 'showing_id');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function tickets_available() {
|
||||||
|
$tickets = $this->room->seats()->count();
|
||||||
|
$tickets_sold = $this->tickets()->count();
|
||||||
|
return $tickets - $tickets_sold;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function find($id)
|
||||||
|
{
|
||||||
|
return Showing::where('showing_id', $id)->first();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function seatMatrix() {
|
||||||
|
return $this->room->seatMatrix($this->showing_id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,9 +62,6 @@ public function permissions()
|
||||||
|
|
||||||
public function allowedTo($permission): bool
|
public function allowedTo($permission): bool
|
||||||
{
|
{
|
||||||
if($this->role === 'manage') {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if ($this->permissions()->where('permission_name', $permission)->first()) {
|
if ($this->permissions()->where('permission_name', $permission)->first()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,14 +25,20 @@ public function __construct(int $room_id, int $showing_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
public function matrixGenerate() {
|
public function matrixGenerate() {
|
||||||
$matrix = [];
|
// returns a matrix of seats
|
||||||
for ($row = 1; $row <= $this->room->room_rows; $row++) {
|
$m = [];
|
||||||
$matrix[$row] = [];
|
// first make empty matrix
|
||||||
for ($column = 1; $column <= $this->room->room_columns; $column++) {
|
for ($i = 0; $i < $this->room->room_rows-1; $i++) {
|
||||||
$matrix[$row][$column] = 0;
|
$m[$i] = [];
|
||||||
|
for ($j = 0; $j < $this->room->room_columns-1; $j++) {
|
||||||
|
$m[$i][$j] = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return $matrix;
|
$seats = $this->room->seats;
|
||||||
|
foreach ($seats as $seat) {
|
||||||
|
$m[$seat->seat_row][$seat->seat_column] = $seat;
|
||||||
|
}
|
||||||
|
return $m;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
"laravel/tinker": "^2.7"
|
"laravel/tinker": "^2.7"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
|
"barryvdh/laravel-debugbar": "^3.7",
|
||||||
"fakerphp/faker": "^1.9.1",
|
"fakerphp/faker": "^1.9.1",
|
||||||
"laravel/pint": "^1.0",
|
"laravel/pint": "^1.0",
|
||||||
"laravel/sail": "^1.0.1",
|
"laravel/sail": "^1.0.1",
|
||||||
|
|
152
composer.lock
generated
152
composer.lock
generated
|
@ -4,7 +4,7 @@
|
||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "8c432fe5b25b92e8fcd080943fcdb6a1",
|
"content-hash": "3ae872d179c399882f9ee7cadecede4c",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "brick/math",
|
"name": "brick/math",
|
||||||
|
@ -5433,6 +5433,90 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"packages-dev": [
|
"packages-dev": [
|
||||||
|
{
|
||||||
|
"name": "barryvdh/laravel-debugbar",
|
||||||
|
"version": "v3.7.0",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/barryvdh/laravel-debugbar.git",
|
||||||
|
"reference": "3372ed65e6d2039d663ed19aa699956f9d346271"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/barryvdh/laravel-debugbar/zipball/3372ed65e6d2039d663ed19aa699956f9d346271",
|
||||||
|
"reference": "3372ed65e6d2039d663ed19aa699956f9d346271",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"illuminate/routing": "^7|^8|^9",
|
||||||
|
"illuminate/session": "^7|^8|^9",
|
||||||
|
"illuminate/support": "^7|^8|^9",
|
||||||
|
"maximebf/debugbar": "^1.17.2",
|
||||||
|
"php": ">=7.2.5",
|
||||||
|
"symfony/finder": "^5|^6"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"mockery/mockery": "^1.3.3",
|
||||||
|
"orchestra/testbench-dusk": "^5|^6|^7",
|
||||||
|
"phpunit/phpunit": "^8.5|^9.0",
|
||||||
|
"squizlabs/php_codesniffer": "^3.5"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"branch-alias": {
|
||||||
|
"dev-master": "3.6-dev"
|
||||||
|
},
|
||||||
|
"laravel": {
|
||||||
|
"providers": [
|
||||||
|
"Barryvdh\\Debugbar\\ServiceProvider"
|
||||||
|
],
|
||||||
|
"aliases": {
|
||||||
|
"Debugbar": "Barryvdh\\Debugbar\\Facades\\Debugbar"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"files": [
|
||||||
|
"src/helpers.php"
|
||||||
|
],
|
||||||
|
"psr-4": {
|
||||||
|
"Barryvdh\\Debugbar\\": "src/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Barry vd. Heuvel",
|
||||||
|
"email": "barryvdh@gmail.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "PHP Debugbar integration for Laravel",
|
||||||
|
"keywords": [
|
||||||
|
"debug",
|
||||||
|
"debugbar",
|
||||||
|
"laravel",
|
||||||
|
"profiler",
|
||||||
|
"webprofiler"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/barryvdh/laravel-debugbar/issues",
|
||||||
|
"source": "https://github.com/barryvdh/laravel-debugbar/tree/v3.7.0"
|
||||||
|
},
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"url": "https://fruitcake.nl",
|
||||||
|
"type": "custom"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://github.com/barryvdh",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"time": "2022-07-11T09:26:42+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "doctrine/instantiator",
|
"name": "doctrine/instantiator",
|
||||||
"version": "1.4.1",
|
"version": "1.4.1",
|
||||||
|
@ -5879,6 +5963,72 @@
|
||||||
},
|
},
|
||||||
"time": "2022-11-15T14:36:57+00:00"
|
"time": "2022-11-15T14:36:57+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "maximebf/debugbar",
|
||||||
|
"version": "v1.18.1",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/maximebf/php-debugbar.git",
|
||||||
|
"reference": "ba0af68dd4316834701ecb30a00ce9604ced3ee9"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/maximebf/php-debugbar/zipball/ba0af68dd4316834701ecb30a00ce9604ced3ee9",
|
||||||
|
"reference": "ba0af68dd4316834701ecb30a00ce9604ced3ee9",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": "^7.1|^8",
|
||||||
|
"psr/log": "^1|^2|^3",
|
||||||
|
"symfony/var-dumper": "^2.6|^3|^4|^5|^6"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"phpunit/phpunit": "^7.5.20 || ^9.4.2",
|
||||||
|
"twig/twig": "^1.38|^2.7|^3.0"
|
||||||
|
},
|
||||||
|
"suggest": {
|
||||||
|
"kriswallsmith/assetic": "The best way to manage assets",
|
||||||
|
"monolog/monolog": "Log using Monolog",
|
||||||
|
"predis/predis": "Redis storage"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"branch-alias": {
|
||||||
|
"dev-master": "1.18-dev"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"DebugBar\\": "src/DebugBar/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Maxime Bouroumeau-Fuseau",
|
||||||
|
"email": "maxime.bouroumeau@gmail.com",
|
||||||
|
"homepage": "http://maximebf.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Barry vd. Heuvel",
|
||||||
|
"email": "barryvdh@gmail.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Debug bar in the browser for php application",
|
||||||
|
"homepage": "https://github.com/maximebf/php-debugbar",
|
||||||
|
"keywords": [
|
||||||
|
"debug",
|
||||||
|
"debugbar"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/maximebf/php-debugbar/issues",
|
||||||
|
"source": "https://github.com/maximebf/php-debugbar/tree/v1.18.1"
|
||||||
|
},
|
||||||
|
"time": "2022-03-31T14:55:54+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "mockery/mockery",
|
"name": "mockery/mockery",
|
||||||
"version": "1.5.1",
|
"version": "1.5.1",
|
||||||
|
|
|
@ -19,8 +19,8 @@ public function up()
|
||||||
$table->string('cinema_name');
|
$table->string('cinema_name');
|
||||||
$table->foreignId('address_id')->constrained('addresses', 'address_id');
|
$table->foreignId('address_id')->constrained('addresses', 'address_id');
|
||||||
$table->foreignId('user_id')->constrained('users', 'user_id'); // who created this cinema
|
$table->foreignId('user_id')->constrained('users', 'user_id'); // who created this cinema
|
||||||
$table->timestamp('cinema_open')->nullable();
|
$table->time('cinema_open');
|
||||||
$table->timestamp('cinema_close')->nullable();
|
$table->time('cinema_close');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,8 @@ public function up()
|
||||||
$table->timestamps();
|
$table->timestamps();
|
||||||
$table->addColumn('integer', 'seat_row');
|
$table->addColumn('integer', 'seat_row');
|
||||||
$table->addColumn('integer', 'seat_column');
|
$table->addColumn('integer', 'seat_column');
|
||||||
$table->addColumn('enum', 'seat_type', ['values' => ['standard', 'wheelchair', 'loveseat']]);
|
$table->enum('seat_type', ['standard', 'wheelchair', 'loveseat', 'not_available']);
|
||||||
|
$table->foreignId('seat_linked_id')->nullable()->constrained('seats', 'seat_id');
|
||||||
$table->foreignId('room_id')->constrained('rooms', 'room_id');
|
$table->foreignId('room_id')->constrained('rooms', 'room_id');
|
||||||
$table->unique(['room_id', 'seat_row', 'seat_column']);
|
$table->unique(['room_id', 'seat_row', 'seat_column']);
|
||||||
});
|
});
|
||||||
|
|
|
@ -25,6 +25,8 @@ public function run()
|
||||||
'address_zip' => '12345',
|
'address_zip' => '12345',
|
||||||
'address_phone' => '123-456-7890',
|
'address_phone' => '123-456-7890',
|
||||||
],
|
],
|
||||||
|
'cinema_open' => '10:00:00',
|
||||||
|
'cinema_close' => '22:00:00',
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'cinema_name' => 'Cinema 2',
|
'cinema_name' => 'Cinema 2',
|
||||||
|
@ -36,6 +38,8 @@ public function run()
|
||||||
'address_zip' => '12345',
|
'address_zip' => '12345',
|
||||||
'address_phone' => '123-456-7890',
|
'address_phone' => '123-456-7890',
|
||||||
],
|
],
|
||||||
|
'cinema_open' => '12:00:00',
|
||||||
|
'cinema_close' => '23:00:00',
|
||||||
]
|
]
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -44,6 +48,8 @@ public function run()
|
||||||
$c = new \App\Models\Cinema();
|
$c = new \App\Models\Cinema();
|
||||||
$c->cinema_name = $cinema['cinema_name'];
|
$c->cinema_name = $cinema['cinema_name'];
|
||||||
$c->user_id = 1;
|
$c->user_id = 1;
|
||||||
|
$c->cinema_open = $cinema['cinema_open'];
|
||||||
|
$c->cinema_close = $cinema['cinema_close'];
|
||||||
|
|
||||||
$a = new \App\Models\Address();
|
$a = new \App\Models\Address();
|
||||||
$a->address_street = $cinema['cinema_address']['address_line_1'];
|
$a->address_street = $cinema['cinema_address']['address_line_1'];
|
||||||
|
|
|
@ -3,25 +3,16 @@ version: '3.3'
|
||||||
# LARAVEL ENVIRONMENT COMPOSE
|
# LARAVEL ENVIRONMENT COMPOSE
|
||||||
|
|
||||||
services:
|
services:
|
||||||
redis:
|
phpmyadmin:
|
||||||
image: redis:alpine
|
image: phpmyadmin/phpmyadmin
|
||||||
container_name: redis
|
container_name: phpmyadmin
|
||||||
restart: always
|
restart: always
|
||||||
ports:
|
ports:
|
||||||
- "6379:6379"
|
- "8080:80"
|
||||||
|
environment:
|
||||||
memcached:
|
PMA_HOST: neo.faulty.nl
|
||||||
image: memcached:alpine
|
PMA_PORT: 33061
|
||||||
container_name: memcached
|
PMA_USER: laravel
|
||||||
restart: always
|
PMA_PASSWORD: laravel
|
||||||
ports:
|
PMA_ARBITRARY: 1
|
||||||
- "11211:11211"
|
PMA_ABSOLUTE_URI: http://localhost:8080/
|
||||||
|
|
||||||
mailhog:
|
|
||||||
image: mailhog/mailhog
|
|
||||||
container_name: mailhog
|
|
||||||
restart: always
|
|
||||||
ports:
|
|
||||||
- "1025:1025"
|
|
||||||
- "8025:8025"
|
|
||||||
|
|
||||||
|
|
|
@ -171,3 +171,7 @@ .hide {
|
||||||
.op0 {
|
.op0 {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.mono {
|
||||||
|
font-family: monospace;
|
||||||
|
}
|
||||||
|
|
|
@ -168,3 +168,24 @@ form .form-group button:hover {
|
||||||
filter: brightness(1.5);
|
filter: brightness(1.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#showings {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
#showings .showing {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 2fr 1fr 1fr 0.25fr;
|
||||||
|
gap: 0.5rem;
|
||||||
|
margin: 0.5rem 0;
|
||||||
|
padding: 1rem;
|
||||||
|
background: var(--second-bg);
|
||||||
|
border-radius: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
#showings .showing .actions {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
|
@ -1,39 +1,95 @@
|
||||||
:root {
|
/*
|
||||||
--spacing: 1rem;
|
* (C) (C) (C) (C) (C)
|
||||||
}
|
(R) S S S S S
|
||||||
|
(R) S S S S S
|
||||||
|
(R) S S S S S
|
||||||
|
(R) S S S S S
|
||||||
|
...
|
||||||
|
*/
|
||||||
|
|
||||||
.seat-chooser {
|
#seat-chooser {
|
||||||
padding: var(--spacing);
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
position: relative;
|
|
||||||
background: var(--second-bg);
|
|
||||||
border: 1px solid #ccc;
|
|
||||||
border-radius: 5px;
|
|
||||||
overflow: hidden;
|
|
||||||
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: repeat(var(--cols), 1fr);
|
|
||||||
grid-template-rows: repeat(var(--rows), 1fr);
|
|
||||||
gap: var(--spacing);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.seat-chooser .seat {
|
#seat-chooser .row {
|
||||||
position: relative;
|
display: flex;
|
||||||
background: #5f5;
|
flex-direction: row;
|
||||||
border: 1px solid #ccc;
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#seat-chooser .row .seat {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 50px;
|
||||||
|
height: 50px;
|
||||||
|
margin: 5px;
|
||||||
|
border: 1px solid #000;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
overflow: hidden;
|
background-color: #fff;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
width: 32px;
|
|
||||||
height: 32px;
|
|
||||||
transition: all 0.3s ease;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.seat-chooser .seat.seat-reserved {
|
#seat-chooser .row .seat.linked-left {
|
||||||
background: #f66;
|
border-top-right-radius: 0;
|
||||||
|
border-bottom-right-radius: 0;
|
||||||
|
border-right: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.seat-chooser .seat:hover {
|
#seat-chooser .row .seat.linked-right {
|
||||||
background: var(--highlight-bg);
|
border-top-left-radius: 0;
|
||||||
|
border-bottom-left-radius: 0;
|
||||||
|
border-left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#seat-chooser .row .no-seat {
|
||||||
|
/* this seat DOES NOT EXISTS it's a filler for layout*/
|
||||||
|
border: none;
|
||||||
|
background-color: transparent;
|
||||||
|
cursor: default;
|
||||||
|
width: 50px;
|
||||||
|
height: 50px;
|
||||||
|
margin: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#seat-chooser .row .seat.selected {
|
||||||
|
background-color: #55f;
|
||||||
|
}
|
||||||
|
|
||||||
|
#seat-chooser .row .seat.reserved {
|
||||||
|
background-color: #f00;
|
||||||
|
}
|
||||||
|
|
||||||
|
#seat-chooser .row .seat:hover {
|
||||||
|
filter: brightness(0.8);
|
||||||
|
}
|
||||||
|
|
||||||
|
#load-screen {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background-color: #000;
|
||||||
|
z-index: 9999;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.spinner {
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
border: 4px solid #f3f3f3;
|
||||||
|
border-top: 4px solid #3498db;
|
||||||
|
border-radius: 50%;
|
||||||
|
animation: spin 2s linear infinite;
|
||||||
}
|
}
|
||||||
|
|
129
public/js/seat-chooser.js
Normal file
129
public/js/seat-chooser.js
Normal file
|
@ -0,0 +1,129 @@
|
||||||
|
// this file should contain a class that gets info from /api/showings/{id}
|
||||||
|
// and renders the seat chooser
|
||||||
|
// there may be multiple seats selected at once
|
||||||
|
// the input is a matrix with null OR a seat object
|
||||||
|
|
||||||
|
class Seat {
|
||||||
|
constructor(id, row, col, linked, reserved) {
|
||||||
|
this.id = id; // database id
|
||||||
|
this.row = row;
|
||||||
|
this.col = col;
|
||||||
|
this.linked = linked; // linked seat
|
||||||
|
this.reserved = reserved;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class SeatChooser {
|
||||||
|
constructor(showingId, container) {
|
||||||
|
if (container.innerText === '') {
|
||||||
|
container.innerText = 'Loading...';
|
||||||
|
}
|
||||||
|
this.showingId = showingId; // id of the showing
|
||||||
|
this.container = container; // the container to render the seat chooser in
|
||||||
|
|
||||||
|
this.seats = []; // array of nulls and Seat objects
|
||||||
|
|
||||||
|
this.selectedSeats = []; // array of Seat objects
|
||||||
|
|
||||||
|
this.init();
|
||||||
|
}
|
||||||
|
|
||||||
|
async init() {
|
||||||
|
let showingJson = await (await fetch(`/api/showings/${this.showingId}`)).json();
|
||||||
|
let roomMatrix = await (await fetch(`/api/showings/${this.showingId}/seatMatrix`)).json();
|
||||||
|
// Matrix<json | null> -> Matrix<Seat | null>
|
||||||
|
console.log("Matrix<json | null> -> Matrix<Seat | null>");
|
||||||
|
this.seats = roomMatrix.map((row, rowIndex) => {
|
||||||
|
return row.map((seat, colIndex) => {
|
||||||
|
if (seat === null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return new Seat(
|
||||||
|
seat['seat_id'],
|
||||||
|
seat['seat_row'],
|
||||||
|
seat['seat_column'],
|
||||||
|
seat['seat_linked_id'],
|
||||||
|
seat['reserved']
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
console.log(this.seats);
|
||||||
|
this.render();
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
console.log("rendering");
|
||||||
|
let linkedCache = false;
|
||||||
|
// render the seat chooser
|
||||||
|
this.container.innerHTML = '';
|
||||||
|
// this -> row -> seat
|
||||||
|
this.seats.forEach((row, rowIndex) => {
|
||||||
|
let rowDiv = document.createElement('div');
|
||||||
|
rowDiv.classList.add('row');
|
||||||
|
row.forEach((seat, colIndex) => {
|
||||||
|
let seatDiv = document.createElement('div');
|
||||||
|
if (seat) {
|
||||||
|
seatDiv.classList.add('seat');
|
||||||
|
seatDiv.classList.add(seat.reserved ? 'reserved' : 'available');
|
||||||
|
|
||||||
|
if (seat.linked) {
|
||||||
|
// if cache is false, then this is the first seat in the linked pair
|
||||||
|
if (!linkedCache) {
|
||||||
|
seatDiv.classList.add('linked-left');
|
||||||
|
linkedCache = true;
|
||||||
|
} else {
|
||||||
|
seatDiv.classList.add('linked-right');
|
||||||
|
linkedCache = false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
linkedCache = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
seatDiv.innerText = `${seat.row}-${seat.col}`;
|
||||||
|
|
||||||
|
seatDiv.dataset.id = seat.id;
|
||||||
|
seatDiv.dataset.row = seat.row;
|
||||||
|
seatDiv.dataset.col = seat.col;
|
||||||
|
|
||||||
|
seatDiv.addEventListener('click', (e) => {
|
||||||
|
this.toggleSeat(seat, e);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
seatDiv.classList.add('no-seat');
|
||||||
|
}
|
||||||
|
rowDiv.appendChild(seatDiv);
|
||||||
|
});
|
||||||
|
this.container.appendChild(rowDiv);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleSeat(seat, e) {
|
||||||
|
// toggle the seat
|
||||||
|
// because of linked seats, we need to toggle both seats
|
||||||
|
if (seat.reserved) return;
|
||||||
|
e.target.classList.toggle('selected');
|
||||||
|
if (seat.linked) {
|
||||||
|
// beware that you can click on the left or right seat
|
||||||
|
// the left seat has class linked-left and the right seat has class linked-right
|
||||||
|
let leftbool = e.target.classList.contains('linked-left');
|
||||||
|
let linkedSeat = this.seats[seat.row - 1][leftbool ? seat.col - 1 : seat.col + 1];
|
||||||
|
if (leftbool) e.target.nextElementSibling.classList.toggle('selected');
|
||||||
|
else e.target.previousElementSibling.classList.toggle('selected');
|
||||||
|
if (this.selectedSeats.includes(linkedSeat)) {
|
||||||
|
this.selectedSeats.splice(this.selectedSeats.indexOf(linkedSeat), 1);
|
||||||
|
this.selectedSeats.splice(this.selectedSeats.indexOf(seat), 1);
|
||||||
|
} else {
|
||||||
|
this.selectedSeats.push(linkedSeat);
|
||||||
|
this.selectedSeats.push(seat);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (this.selectedSeats.includes(seat)) {
|
||||||
|
this.selectedSeats.splice(this.selectedSeats.indexOf(seat), 1);
|
||||||
|
} else {
|
||||||
|
this.selectedSeats.push(seat);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let seatChooser = new SeatChooser(1, document.getElementById('seat-chooser'));
|
33
resources/views/components/seat-chooser.blade.old.php
Normal file
33
resources/views/components/seat-chooser.blade.old.php
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
@extends('layout')
|
||||||
|
|
||||||
|
@push('head')
|
||||||
|
<link rel="stylesheet" href="{{ asset('css/seat-chooser.css') }}">
|
||||||
|
<script src="{{ asset('js/seat-chooser.js') }}" defer></script>
|
||||||
|
@endpush
|
||||||
|
|
||||||
|
<div id="load-screen">
|
||||||
|
<div id="loading">
|
||||||
|
<div class="spinner"></div>
|
||||||
|
<div class="loading-text">Loading...</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="seat-chooser">
|
||||||
|
@foreach($seatmatrix as $row)
|
||||||
|
<div class="row">
|
||||||
|
@foreach($row as $seat)
|
||||||
|
@if($seat)
|
||||||
|
<div class="seat @if($seat->isReserved($showing_id)) reserved @endif"
|
||||||
|
data-seat-id="{{ $seat->seat_id }}"
|
||||||
|
data-seat-status="{{ $seat->seat_status }}"
|
||||||
|
data-seat-row="{{ $seat->seat_row }}"
|
||||||
|
data-seat-column="{{ $seat->seat_column }}">
|
||||||
|
<div class="seat-number">{{ $seat->seat_row }}-{{ $seat->seat_column }}</div>
|
||||||
|
</div>
|
||||||
|
@else
|
||||||
|
<div class="no-seat"></div>
|
||||||
|
@endif
|
||||||
|
@endforeach
|
||||||
|
</div>
|
||||||
|
@endforeach
|
||||||
|
</div>
|
|
@ -2,26 +2,7 @@
|
||||||
|
|
||||||
@push('head')
|
@push('head')
|
||||||
<link rel="stylesheet" href="{{ asset('css/seat-chooser.css') }}">
|
<link rel="stylesheet" href="{{ asset('css/seat-chooser.css') }}">
|
||||||
<style>
|
<script src="{{ asset('js/seat-chooser.js') }}" defer></script>
|
||||||
:root {
|
|
||||||
--rows: {{ $room->room_rows }};
|
|
||||||
--cols: {{ $room->room_columns }};
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@endpush
|
@endpush
|
||||||
|
|
||||||
<div class="seat-chooser">
|
<div id="seat-chooser"></div>
|
||||||
@foreach($seatmatrix as $row)
|
|
||||||
<div class="row">
|
|
||||||
@foreach($row as $seat)
|
|
||||||
<div class="seat @if($seat->isReserved) reserved @endif"
|
|
||||||
data-seat-id="{{ $seat->seat_id }}"
|
|
||||||
data-seat-status="{{ $seat->seat_status }}"
|
|
||||||
data-seat-row="{{ $seat->seat_row }}"
|
|
||||||
data-seat-column="{{ $seat->seat_column }}">
|
|
||||||
<div class="seat-number">{{ $seat->seat_row }}{{ $seat->seat_column }}</div>
|
|
||||||
</div>
|
|
||||||
@endforeach
|
|
||||||
</div>
|
|
||||||
@endforeach
|
|
||||||
</div>
|
|
||||||
|
|
34
resources/views/main/cinemas/cinema.blade.php
Normal file
34
resources/views/main/cinemas/cinema.blade.php
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
@extends('main.layout')
|
||||||
|
|
||||||
|
@section('content')
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<h1>{{$cinema->cinema_name}}</h1>
|
||||||
|
<hr/>
|
||||||
|
<div id="cinema">
|
||||||
|
<div class="details">
|
||||||
|
<span>{{$cinema->address->string()}}</span><br/>
|
||||||
|
<span>{{$cinema->cinema_open}} - {{$cinema->cinema_close}}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<h1>Now playing:</h1>
|
||||||
|
<hr/>
|
||||||
|
<div id="showings">
|
||||||
|
@foreach($cinema->showings as $showing)
|
||||||
|
<a href="/showing/{{$showing->showing_id}}">
|
||||||
|
<img src="{{$showing->movie->movie_image}}" alt="{{$showing->movie->movie_name}} Poster"
|
||||||
|
width="200px">
|
||||||
|
<div class="details">
|
||||||
|
<span>{{$showing->movie->movie_name}}</span><br/>
|
||||||
|
<span>{{$showing->showing_date}}</span><br/>
|
||||||
|
<span>{{$showing->showing_time}}</span>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
@endforeach
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
@endsection
|
30
resources/views/main/genres/genre.blade.php
Normal file
30
resources/views/main/genres/genre.blade.php
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
@extends('main.layout')
|
||||||
|
|
||||||
|
@section('content')
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<h1>{{$genre->genre_name}}</h1>
|
||||||
|
<hr/>
|
||||||
|
<div id="genre">
|
||||||
|
<div class="details">
|
||||||
|
<span>{{$genre->genre_description}}</span><br/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<h1>Movies:</h1>
|
||||||
|
<hr/>
|
||||||
|
<div id="movies">
|
||||||
|
@foreach($genre->movies as $movie)
|
||||||
|
<a href="/movie/{{$movie->movie_id}}">
|
||||||
|
<img src="{{$movie->movie_image}}" alt="{{$movie->movie_name}} Poster" width="200px">
|
||||||
|
<div class="details">
|
||||||
|
<span>{{$movie->movie_name}}</span><br/>
|
||||||
|
<span>{{$movie->movie_length}} min</span>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
@endforeach
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
@endsection
|
|
@ -1,20 +1,17 @@
|
||||||
@extends('main.layout')
|
@extends('main.layout')
|
||||||
|
|
||||||
|
@push('head')
|
||||||
|
<link rel="stylesheet" href="{{asset('css/movies.css')}}">
|
||||||
|
@endpush
|
||||||
|
|
||||||
@section('content')
|
@section('content')
|
||||||
|
|
||||||
<section>
|
<section>
|
||||||
<h1>Now playing:</h1>
|
<h1>Now playing:</h1>
|
||||||
<hr/>
|
<hr/>
|
||||||
<div id="movies">
|
<div id="movies">
|
||||||
@foreach($showings as $showing)
|
@foreach($movies as $showing)
|
||||||
<a href="/movie/{{$showing->movie->movie_id}}">
|
|
||||||
<img src="{{$showing->movie->movie_image}}" alt="{{$showing->movie->movie_name}} Poster"
|
|
||||||
width="200px">
|
|
||||||
<div class="details">
|
|
||||||
<span>{{$showing->movie->movie_name}}</span><br/>
|
|
||||||
<span>{{$showing->movie->movie_length}} min</span>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
@endforeach
|
@endforeach
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
|
37
resources/views/main/showings/showing.blade.php
Normal file
37
resources/views/main/showings/showing.blade.php
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
@extends('main.layout')
|
||||||
|
|
||||||
|
@section('content')
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<h1><img src="{{$showing->movie->movie_image}}" alt="{{$showing->movie->movie_name}} Poster" width="60px">
|
||||||
|
{{$showing->movie->movie_name}}</h1>
|
||||||
|
<hr/>
|
||||||
|
<div id="showing">
|
||||||
|
<div class="details">
|
||||||
|
<span>Cinema: <a
|
||||||
|
href="/cinema/{{$showing->room->cinema->cinema_id}}">{{$showing->room->cinema->cinema_name}}</a></span><br/>
|
||||||
|
<span>Showing: {{$showing->showing_start}} - {{$showing->end_time()}}</span><br/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<h1>Details</h1>
|
||||||
|
<hr/>
|
||||||
|
<span>{{$showing->movie->movie_description}}</span><br/>
|
||||||
|
<hr/>
|
||||||
|
<span>Runtime: {{$showing->movie->movie_length }} minutes</span><br/>
|
||||||
|
<span>Year: {{$showing->movie->movie_year}}</span><br/>
|
||||||
|
<span>Age limit: {{$showing->movie->movie_age_limit}}</span><br/>
|
||||||
|
<span>Genre: <a
|
||||||
|
href="/genre/{{$showing->movie->genre->genre_id}}">{{$showing->movie->genre->genre_name}}</a></span><br/>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<h1>Tickets:</h1>
|
||||||
|
<hr/>
|
||||||
|
<span>Tickets available: {{$showing->tickets_available()}}</span><br/>
|
||||||
|
<span>Buy tickets?</span>
|
||||||
|
{{-- todo--}}
|
||||||
|
</section>
|
||||||
|
@endsection
|
|
@ -1,7 +1,7 @@
|
||||||
{{-- Layout for admins --}}
|
{{-- Layout for admins --}}
|
||||||
{{-- Will have a sidebar with links --}}
|
{{-- Will have a sidebar with links --}}
|
||||||
{{-- Will have a top bar with account and link to main site--}}
|
{{-- Will have a top bar with account and link to main site--}}
|
||||||
{{--@extends('layout')--}}
|
@extends('layout')
|
||||||
|
|
||||||
@push('head')
|
@push('head')
|
||||||
<link rel="stylesheet" href="{{ asset('css/generic.css') }}">
|
<link rel="stylesheet" href="{{ asset('css/generic.css') }}">
|
||||||
|
@ -19,9 +19,10 @@
|
||||||
<div id="sidebar"> {{-- Page Aware --}}
|
<div id="sidebar"> {{-- Page Aware --}}
|
||||||
<a class="{{ Request::is('manage') ? 'active' : '' }}" href="{{ route('manage') }}">Dashboard</a>
|
<a class="{{ Request::is('manage') ? 'active' : '' }}" href="{{ route('manage') }}">Dashboard</a>
|
||||||
{{-- manage cinemas--}}
|
{{-- manage cinemas--}}
|
||||||
<a class="{{ Request::is('manage/cinemas') ? 'active' : '' }}" href="{{ route('manage.cinemas') }}">Cinemas</a>
|
{{-- <a class="{{ Request::is('manage/cinemas') ? 'active' : '' }}" href="{{ route('manage.cinemas') }}">Cinemas</a>--}}
|
||||||
{{-- <a class="{{ Request::is('manage/cinemas/employees') ? 'active' : '' }} child" href="{{ route('manage.cinemas.employees') }}">Employees</a>--}}
|
{{-- <a class="{{ Request::is('manage/cinemas/employees') ? 'active' : '' }} child" href="{{ route('manage.cinemas.employees') }}">Employees</a>--}}
|
||||||
<a class="{{ Request::is('manage/movies') ? 'active' : '' }}" href="{{ route('manage.movies') }}">Movies</a>
|
<a class="{{ Request::is('manage/movies') ? 'active' : '' }}" href="{{ route('manage.movies') }}">Movies</a>
|
||||||
|
<a class="child {{ Request::is('manage/showings') ? 'active' : '' }}" href="{{ route('manage.showings') }}">Showings</a>
|
||||||
<a class="{{ Request::is('manage/genres') ? 'active' : '' }}" href="{{ route('manage.genres') }}">Genres</a>
|
<a class="{{ Request::is('manage/genres') ? 'active' : '' }}" href="{{ route('manage.genres') }}">Genres</a>
|
||||||
</div>
|
</div>
|
||||||
<main>
|
<main>
|
||||||
|
|
32
resources/views/manage/showings/index.blade.php
Normal file
32
resources/views/manage/showings/index.blade.php
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
@extends('manage.layout')
|
||||||
|
|
||||||
|
@section('content')
|
||||||
|
<h1>Showing Management</h1>
|
||||||
|
<div id="showings">
|
||||||
|
@foreach($showings as $showing)
|
||||||
|
<div class="showing">
|
||||||
|
<div class="movie">
|
||||||
|
<h2>{{ $showing->movie->movie_name }}</h2>
|
||||||
|
<p>{{ $showing->movie->movie_description }}</p>
|
||||||
|
<p>{{ $showing->movie->genre->genre_name }}</p>
|
||||||
|
</div>
|
||||||
|
<div class="cinema">
|
||||||
|
<h3>{{ $showing->room->cinema->cinema_name }} - {{ $showing->room->room_name }}</h3>
|
||||||
|
<p>{{ $showing->room->cinema->address->string() }}</p>
|
||||||
|
</div>
|
||||||
|
<div class="time">
|
||||||
|
<h3>Times</h3>
|
||||||
|
<span class="mono">
|
||||||
|
Start: {{ $showing->showing_start }}<br>
|
||||||
|
Ends : {{ $showing->end_time() }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="actions">
|
||||||
|
<a class="button" href="{{ route('manage.showing', ['id' => $showing->showing_id]) }}">Edit</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
@endforeach
|
||||||
|
</div>
|
||||||
|
<a href="{{ route('manage.showings.create') }}">Create Showing</a>
|
||||||
|
@endsection
|
84
resources/views/manage/showings/showing.blade.php
Normal file
84
resources/views/manage/showings/showing.blade.php
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
@extends('manage.layout')
|
||||||
|
|
||||||
|
@section('content')
|
||||||
|
<h1>Showing - {{ $showing->showing_start }}</h1>
|
||||||
|
<form method="POST" action="{{ route('manage.showing', ['id' => $showing->showing_id]) }}" class="form">
|
||||||
|
@csrf
|
||||||
|
@method('PUT')
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="movie_id">Movie</label>
|
||||||
|
<select name="movie_id" id="movie_id">
|
||||||
|
@foreach($movies as $movie)
|
||||||
|
<option value="{{ $movie->movie_id }}" {{ $movie->movie_id == $showing->movie_id ? 'selected' : '' }}>{{ $movie->movie_name }}</option>
|
||||||
|
@endforeach
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="showing_start">Showing Start</label>
|
||||||
|
<input type="datetime-local" name="showing_start" id="showing_start" value="{{ $showing->showing_start }}">
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="room_id">Cinema</label>
|
||||||
|
<select name="cinema_id" id="cinema_id">
|
||||||
|
@foreach($cinemas as $cinema)
|
||||||
|
<option value="{{ $cinema->cinema_id }}" {{ $cinema->cinema_id == $showing->room->cinema_id ? 'selected' : '' }}>{{ $cinema->cinema_name }}</option>
|
||||||
|
@endforeach
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="room_id">Room</label>
|
||||||
|
<select name="room_id" id="room_id">
|
||||||
|
@foreach($showing->room->cinema->rooms as $room)
|
||||||
|
<option value="{{ $room->room_id }}" {{ $room->room_id == $showing->room_id ? 'selected' : '' }}>{{ $room->room_name }}</option>
|
||||||
|
@endforeach
|
||||||
|
</select>
|
||||||
|
<script>
|
||||||
|
// select the current room
|
||||||
|
document.getElementById('cinema_id').addEventListener('change', function() {
|
||||||
|
var cinema_id = this.value;
|
||||||
|
var room_id = document.getElementById('room_id');
|
||||||
|
var rooms = @json($rooms);
|
||||||
|
var options = '';
|
||||||
|
for (var i = 0; i < rooms.length; i++) {
|
||||||
|
if (rooms[i].cinema_id == cinema_id) {
|
||||||
|
options += '<option value="' + rooms[i].room_id + '">' + rooms[i].room_name + '</option>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
room_id.innerHTML = options;
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</div>
|
||||||
|
<script>
|
||||||
|
document.getElementById('cinema_id').addEventListener('change', function() {
|
||||||
|
var cinema_id = this.value;
|
||||||
|
var room_id = document.getElementById('room_id');
|
||||||
|
room_id.innerHTML = '';
|
||||||
|
fetch('/api/cinemas/' + cinema_id + '/rooms')
|
||||||
|
.then(function(response) {
|
||||||
|
return response.json();
|
||||||
|
})
|
||||||
|
.then(function(rooms) {
|
||||||
|
rooms.forEach(function(room) {
|
||||||
|
var option = document.createElement('option');
|
||||||
|
option.value = room.room_id;
|
||||||
|
option.innerHTML = room.room_name;
|
||||||
|
if (room.room_id == {{ $showing->room_id }}) {
|
||||||
|
option.selected = true;
|
||||||
|
}
|
||||||
|
room_id.appendChild(option);
|
||||||
|
});
|
||||||
|
room_id.disabled = false;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
<div class="form-group">
|
||||||
|
<button type="submit" class="button">Update Showing</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</form>
|
||||||
|
<form method="POST" action="{{ route('manage.showing', ['id' => $showing->showing_id]) }}">
|
||||||
|
@csrf
|
||||||
|
@method('DELETE')
|
||||||
|
<button type="submit" class="button">Delete Showing</button>
|
||||||
|
</form>
|
||||||
|
@endsection
|
|
@ -17,3 +17,28 @@
|
||||||
Route::middleware('auth:sanctum')->get('/user', function (Request $request) {
|
Route::middleware('auth:sanctum')->get('/user', function (Request $request) {
|
||||||
return $request->user();
|
return $request->user();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// /api/cinemas/{id}/rooms
|
||||||
|
Route::get('/cinemas/{id}/rooms', function ($id) {
|
||||||
|
$cinema = (new App\Models\Cinema)->find($id);
|
||||||
|
return $cinema->rooms;
|
||||||
|
});
|
||||||
|
|
||||||
|
// /api/showings/{id}
|
||||||
|
Route::get('/showings/{id}', function ($id) {
|
||||||
|
$showing = (new App\Models\Showing)->find($id);
|
||||||
|
return $showing;
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// /api/rooms/{id}/seatMatrix
|
||||||
|
Route::get('/rooms/{id}/seatMatrix', function ($id) {
|
||||||
|
$room = (new App\Models\Room)->find($id);
|
||||||
|
return $room->seatMatrix();
|
||||||
|
});
|
||||||
|
|
||||||
|
// /api/showings/{id}/seatMatrix
|
||||||
|
Route::get('/showings/{id}/seatMatrix', function ($id) {
|
||||||
|
$showing = (new App\Models\Showing)->find($id);
|
||||||
|
return $showing->seatMatrix();
|
||||||
|
});
|
||||||
|
|
|
@ -21,25 +21,15 @@
|
||||||
|
|
||||||
Route::get('/movies', function () {
|
Route::get('/movies', function () {
|
||||||
$s = new \App\Models\Showing();
|
$s = new \App\Models\Showing();
|
||||||
return view('main.movies', ['title' => "Movies", "showings" => $s->nowPlaying()->unique('movie_id')]);
|
return view('main.movies.index', ['title' => "Movies", "showings" => $s->nowPlaying()->unique('movie_id')]);
|
||||||
})->name('movies');
|
})->name('movies');
|
||||||
|
|
||||||
Route::get('/movie/{id}', function ($id) {
|
Route::get('/movie/{id}', function ($id) {
|
||||||
$m = new \App\Models\Movie();
|
$m = new \App\Models\Movie();
|
||||||
$movie = $m->find($id);
|
$movie = $m->find($id);
|
||||||
return view('main.movie', ['title' => $movie->movie_name, "movie" => $movie]);
|
return view('main.movies.movie', ['title' => $movie->movie_name, "movie" => $movie]);
|
||||||
})->name('movie');
|
})->name('movie');
|
||||||
|
|
||||||
Route::get('/cinemas', function () {
|
|
||||||
return view('main.cinemas', ['title' => "Cinemas", "cinemas" => \App\Models\Cinema::all()]);
|
|
||||||
})->name('cinemas');
|
|
||||||
|
|
||||||
Route::get('/cinema/{id}', function ($id) {
|
|
||||||
$c = new \App\Models\Cinema();
|
|
||||||
$cinema = $c->find($id);
|
|
||||||
return view('main.cinema', ['title' => $cinema->cinema_name, "cinema" => $cinema]);
|
|
||||||
})->name('cinema');
|
|
||||||
|
|
||||||
Auth::routes();
|
Auth::routes();
|
||||||
|
|
||||||
// account
|
// account
|
||||||
|
@ -50,6 +40,19 @@
|
||||||
// CRUD - Create Read Update Delete
|
// CRUD - Create Read Update Delete
|
||||||
// FB - Frontend Backend
|
// FB - Frontend Backend
|
||||||
|
|
||||||
|
// main
|
||||||
|
Route::get('/cinemas', [App\Http\Controllers\Main\CinemaController::class, 'showAllCinemas'])->name('cinemas');
|
||||||
|
Route::get('/cinema/{id}', [App\Http\Controllers\Main\CinemaController::class, 'show'])->name('cinema');
|
||||||
|
|
||||||
|
Route::get('/showings', [App\Http\Controllers\Main\ShowingController::class, 'showAllShowings'])->name('showings');
|
||||||
|
Route::get('/showing/{id}', [App\Http\Controllers\Main\ShowingController::class, 'show'])->name('showing');
|
||||||
|
|
||||||
|
Route::get('/movies', [App\Http\Controllers\Main\MovieController::class, 'showAllMovies'])->name('movies');
|
||||||
|
Route::get('/movie/{id}', [App\Http\Controllers\Main\MovieController::class, 'show'])->name('movie');
|
||||||
|
|
||||||
|
Route::get('/genres', [App\Http\Controllers\Main\GenreController::class, 'showAllGenres'])->name('genres');
|
||||||
|
Route::get('/genre/{id}', [App\Http\Controllers\Main\GenreController::class, 'show'])->name('genre');
|
||||||
|
|
||||||
// Employee Home Page
|
// Employee Home Page
|
||||||
Route::get('/manage', function () {
|
Route::get('/manage', function () {
|
||||||
if (!auth()->user()->atleast('employee')) {
|
if (!auth()->user()->atleast('employee')) {
|
||||||
|
@ -114,11 +117,26 @@
|
||||||
Route::delete('/manage/cinema/{id}', [\App\Http\Controllers\Managing\CinemaController::class, 'destroy'])->name('manage.cinema');
|
Route::delete('/manage/cinema/{id}', [\App\Http\Controllers\Managing\CinemaController::class, 'destroy'])->name('manage.cinema');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Route::controller(\App\Http\Controllers\Managing\ShowingsController::class)->group(function () {
|
||||||
|
// /manage/showings - CR showings (FB)
|
||||||
|
Route::get('/manage/showings', [\App\Http\Controllers\Managing\ShowingsController::class, 'showAllShowings'])->name('manage.showings');
|
||||||
|
Route::post('/manage/showings', [\App\Http\Controllers\Managing\ShowingsController::class, 'store'])->name('manage.showings');
|
||||||
|
|
||||||
|
// /manage/showings/create - C showing (F)
|
||||||
|
Route::get('/manage/showings/create', [\App\Http\Controllers\Managing\ShowingsController::class, 'createShowing'])->name('manage.showings.create');
|
||||||
|
// no post, handled by POST /showings
|
||||||
|
|
||||||
|
// /manage/showings/{id} - RUD showing (FB)
|
||||||
|
Route::get('/manage/showing/{id}', [\App\Http\Controllers\Managing\ShowingsController::class, 'edit'])->name('manage.showing');
|
||||||
|
Route::put('/manage/showing/{id}', [\App\Http\Controllers\Managing\ShowingsController::class, 'update'])->name('manage.showing');
|
||||||
|
Route::delete('/manage/showing/{id}', [\App\Http\Controllers\Managing\ShowingsController::class, 'destroy'])->name('manage.showing');
|
||||||
|
});
|
||||||
|
|
||||||
// /test/comp/{component}
|
// /test/comp/{component}
|
||||||
Route::get('/test/comp/{component}', function ($component) {
|
Route::get('/test/comp/{component}', function ($component) {
|
||||||
switch ($component) {
|
switch ($component) {
|
||||||
case 'seat-chooser':
|
case 'seat-chooser':
|
||||||
$c = new \App\View\Components\SeatChooser(1);
|
$c = new \App\View\Components\SeatChooser(1, 1);
|
||||||
return $c->render();
|
return $c->render();
|
||||||
default:
|
default:
|
||||||
return "No component found";
|
return "No component found";
|
||||||
|
|
Loading…
Reference in a new issue