Skip to content

Commit

Permalink
Merge pull request #35 from leepeuker/update-movie-logging
Browse files Browse the repository at this point in the history
Update movie logging ui
  • Loading branch information
leepeuker authored Jul 2, 2022
2 parents 21bd2a7 + 2a64219 commit 6edb587
Show file tree
Hide file tree
Showing 9 changed files with 234 additions and 60 deletions.
164 changes: 162 additions & 2 deletions public/js/logMovie.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,177 @@
const elems = document.querySelectorAll('.datepicker_input')
for (const elem of elems) {
const datepicker = new Datepicker(elem, {
// 'format': 'dd.mm.yyyy',
format: 'dd.mm.yyyy',
title: 'Watch date',
})
}

$('#watchDateModal').on('show.bs.modal', function (e) {
const watchModal = document.getElementById('watchDateModal')
watchModal.addEventListener('show.bs.modal', async function (e) {
let movieId = e.relatedTarget.id
let movieTitle = document.getElementById(movieId + '_movieTitle').value
let movieYear = document.getElementById(movieId + '_movieReleaseYear').value

document.getElementById('watchDate').value = ''
document.getElementById('tmdbId').value = movieId
document.getElementById('watchDateModalTitle').innerHTML = movieTitle + ' (' + movieYear + ')'
let ratingNumber = await fetchRating(movieId)
setRatingStars(ratingNumber)
})

watchModal.addEventListener('hidden.bs.modal', function (e) {
document.getElementById('watchDate').value = ''
document.getElementById('tmdbId').value = ''
document.getElementById('watchDateModalTitle').innerHTML = ''

document.getElementById('watchDate').style.borderStyle = ''
document.getElementById('watchDate').style.borderColor = ''
document.getElementById('ratingStars').style.marginTop = '0.5rem'

document.getElementById('watchDateValidationRequiredErrorMessage').classList.remove('d-block')
document.getElementById('watchDateValidationFormatErrorMessage').classList.remove('d-block')

setRatingStars(0)
})

async function fetchRating (tmdbId) {
const response = await fetch('/fetchMovieRatingByTmdbdId?tmdbId=' + tmdbId)

if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`)
}

const data = await response.json()

return data.personalRating
}

function setRatingStars (ratingNumber) {
let skipFirstStar = false

if (ratingNumber == 1 && getRatingFromStars() == 1) {
skipFirstStar = true
}

for (let ratingStarNumber = 1; ratingStarNumber <= 10; ratingStarNumber++) {
document.getElementById('ratingStar' + ratingStarNumber).classList.remove('bi-star-fill')
document.getElementById('ratingStar' + ratingStarNumber).classList.remove('bi-star')

if (ratingStarNumber <= ratingNumber && skipFirstStar === false) {
document.getElementById('ratingStar' + ratingStarNumber).classList.add('bi-star-fill')
} else {
document.getElementById('ratingStar' + ratingStarNumber).classList.add('bi-star')
}
}
}

function getRatingFromStars () {
let rating = 0

for (let ratingStarNumber = 1; ratingStarNumber <= 10; ratingStarNumber++) {
if (document.getElementById('ratingStar' + ratingStarNumber).classList.contains('bi-star') === true) {
break
}

rating = ratingStarNumber
}

return rating
}

function updateRatingStars (e) {
setRatingStars(e.id.substring(20, 10))
}

function getTmdbId () {
return document.getElementById('tmdbId').value
}

function getWatchDate () {
return document.getElementById('watchDate').value
}

const alertPlaceholder = document.getElementById('alerts')
const addAlertMessage = (message, type) => {
const wrapper = document.createElement('div')
wrapper.innerHTML = [`<div class="alert alert-${type} alert-dismissible" role="alert">`, ` <div>${message}</div>`, ' <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>', '</div>'].join('')

alertPlaceholder.append(wrapper)
}

function logMovie () {
let rating = getRatingFromStars()
let tmdbId = getTmdbId()
let watchDate = getWatchDate()
let movieTitle = document.getElementById('watchDateModalTitle').innerHTML

document.getElementById('watchDateValidationRequiredErrorMessage').classList.remove('d-block')
document.getElementById('watchDateValidationFormatErrorMessage').classList.remove('d-block')

if (!watchDate) {
document.getElementById('watchDate').style.borderStyle = 'solid'
document.getElementById('watchDate').style.borderColor = '#dc3545'
document.getElementById('ratingStars').style.marginTop = '0'
document.getElementById('watchDateValidationRequiredErrorMessage').classList.add('d-block')
return
}
if (isValidDate(watchDate) === false) {
document.getElementById('watchDate').style.borderStyle = 'solid'
document.getElementById('watchDate').style.borderColor = '#dc3545'
document.getElementById('ratingStars').style.marginTop = '0'
document.getElementById('watchDateValidationFormatErrorMessage').classList.add('d-block')
return
}

document.getElementById('watchDate').style.borderStyle = ''
document.getElementById('watchDate').style.borderColor = ''
document.getElementById('ratingStars').style.marginTop = '0.5rem'

fetch('/log-movie', {
method: 'post', headers: {
'Content-type': 'application/json',
}, body: JSON.stringify({
'tmdbId': tmdbId, 'watchDate': watchDate, 'personalRating': rating,
})
})
.then(function (response) {
if (response.status === 200) {
addAlertMessage('Added: ' + movieTitle + ' at ' + watchDate, 'success')
} else {
console.log(response)
addAlertMessage('Could not add: ' + movieTitle + ' at ' + watchDate, 'danger')
}

bootstrap.Modal.getInstance(watchModal).hide()
})
.catch(function (error) {
console.log(error)
addAlertMessage('Could not add: ' + movieTitle + ' at ' + watchDate, 'danger')

bootstrap.Modal.getInstance(watchModal).hide()
})
}

function isValidDate (dateString) {
// First check for the pattern
if (!/^\d{1,2}\.\d{1,2}\.\d{4}$/.test(dateString)) {
return false
}

// Parse the date parts to integers
var parts = dateString.split('.')
var day = parseInt(parts[0], 10)
var month = parseInt(parts[1], 10)
var year = parseInt(parts[2], 10)

// Check the ranges of month and year
if (year < 1000 || year > 3000 || month == 0 || month > 12) return false

var monthLength = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]

// Adjust for leap years
if (year % 400 == 0 || (year % 100 != 0 && year % 4 == 0)) monthLength[1] = 29

// Check the range of the day
return day > 0 && day <= monthLength[month - 1]
}
1 change: 0 additions & 1 deletion public/js/movie.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@ function setRatingStars (ratingNumber) {
let skipFirstStar = false

if (ratingNumber == 1 && getRatingFromStars() == 1) {
console.log(ratingNumber, getRatingFromStars())
skipFirstStar = true
}

Expand Down
5 changes: 5 additions & 0 deletions settings/routes.php
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,11 @@
'/log-movie',
[\Movary\HttpController\HistoryController::class, 'logMovie']
);
$routeCollector->addRoute(
'GET',
'/fetchMovieRatingByTmdbdId',
[\Movary\HttpController\MovieController::class, 'fetchMovieRatingByTmdbdId']
);
$routeCollector->addRoute(
'GET',
'/movie/{id:\d+}',
Expand Down
21 changes: 10 additions & 11 deletions src/HttpController/HistoryController.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
use Movary\Util\Json;
use Movary\ValueObject\Date;
use Movary\ValueObject\DateTime;
use Movary\ValueObject\Http\Header;
use Movary\ValueObject\Http\Request;
use Movary\ValueObject\Http\Response;
use Movary\ValueObject\Http\StatusCode;
Expand Down Expand Up @@ -54,11 +53,15 @@ public function logMovie(Request $request) : Response
return Response::createFoundRedirect('/');
}

$postParameters = $request->getPostParameters();
$requestData = Json::decode($request->getBody());

$watchDate = Date::createFromDateTime(DateTime::createFromString($postParameters['watchDate']));
$tmdbId = (int)$postParameters['tmdbId'];
$personalRating = PersonalRating::create((int)$postParameters['personalRating']);
if (isset($requestData['watchDate'], $requestData['tmdbId'], $requestData['personalRating']) === false) {
throw new \RuntimeException('Missing parameters');
}

$watchDate = Date::createFromDateTime(DateTime::createFromString($requestData['watchDate']));
$tmdbId = (int)$requestData['tmdbId'];
$personalRating = $requestData['personalRating'] === 0 ? null : PersonalRating::create((int)$requestData['personalRating']);

$movie = $this->movieApi->findByTmdbId($tmdbId);

Expand All @@ -67,13 +70,9 @@ public function logMovie(Request $request) : Response
}

$this->movieApi->updatePersonalRating($movie->getId(), $personalRating);
$this->movieApi->replaceHistoryForMovieByDate($movie->getId(), $watchDate, 1);
$this->movieApi->increaseHistoryPlaysForMovieOnDate($movie->getId(), $watchDate);

return Response::create(
StatusCode::createSeeOther(),
null,
[Header::createLocation($_SERVER['HTTP_REFERER'])]
);
return Response::create(StatusCode::createOk());
}

public function renderHistory(Request $request) : Response
Expand Down
12 changes: 12 additions & 0 deletions src/HttpController/MovieController.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use Movary\Application\Movie;
use Movary\Application\User\Service\Authentication;
use Movary\Util\Json;
use Movary\ValueObject\Http\Request;
use Movary\ValueObject\Http\Response;
use Movary\ValueObject\Http\StatusCode;
Expand All @@ -19,6 +20,17 @@ public function __construct(
) {
}

public function fetchMovieRatingByTmdbdId(Request $request) : Response
{
$tmdbId = $request->getGetParameters()['tmdbId'] ?? null;

$movie = $this->movieApi->findByTmdbId((int)$tmdbId);

return Response::createJson(
Json::encode(['personalRating' => $movie?->getPersonalRating()?->asInt()])
);
}

public function renderPage(Request $request) : Response
{
$movieId = (int)$request->getRouteParameters()['id'];
Expand Down
10 changes: 5 additions & 5 deletions src/ValueObject/Http/Response.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ public static function create(StatusCode $statusCode, ?string $body = null, arra
return new self($statusCode, $body, $headers);
}

public static function createCsv(string $body) : self
{
return new self(StatusCode::createOk(), $body, [Header::createContentTypeCsv()]);
}

public static function createFoundRedirect(string $targetUrl) : self
{
return new self(StatusCode::createSeeOther(), null, [Header::createLocation($targetUrl)]);
Expand All @@ -29,11 +34,6 @@ public static function createJson(string $body) : self
return new self(StatusCode::createOk(), $body, [Header::createContentTypeJson()]);
}

public static function createCsv(string $body) : self
{
return new self(StatusCode::createOk(), $body, [Header::createContentTypeCsv()]);
}

public static function createNotFound() : self
{
return new self(StatusCode::createNotFound());
Expand Down
44 changes: 31 additions & 13 deletions templates/page/logMovie.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
{% import 'makro/tmdb.html.twig' as tmdb %}

{% block title %}
Person: {{ person.name }}
Log movie
{% endblock %}

{% block stylesheets %}
Expand All @@ -18,7 +18,11 @@
{% block body %}
<main role="main" class="container">
{{ include('component/navbar.html.twig') }}
<div style="text-align: center;padding-top: 1rem" class="clearfix">

<div id="alerts" style="margin-top: 1rem">
</div>

<div style="text-align: center;" class="clearfix">
<form action="/log-movie" method="GET">
<div class="input-group mb-3">
<input type="text" class="form-control" name="s" placeholder="Search" value="{{ (searchTerm is null) ? '' : searchTerm }}">
Expand Down Expand Up @@ -47,26 +51,40 @@

<br>

<div class="modal fade" id="watchDateModal" tabindex="-1" aria-labelledby="watchDateModal" aria-hidden="true">
<div class="modal fade" id="watchDateModal" tabindex="-1" aria-labelledby="watchDateModal" aria-hidden="true" data-bs-backdrop="static" data-bs-keyboard="false" >
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="watchDateModalTitle">Log movie</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<form action="/log-movie" method="POST">
<div class="modal-body">
<input type="hidden" value="" name="tmdbId" id="tmdbId" required>
<div class="input-group">
<i class="bi bi-calendar-date input-group-text"></i>
<input type="text" class="datepicker_input form-control" placeholder="Watch date" aria-label="Watch date" name="watchDate" id="watchDate" required>
<div class="modal-body" style="padding-bottom: 0.4rem">
<input type="hidden" value="" name="tmdbId" id="tmdbId" required>
<div class="input-group" id="watchDateGroup">
<i class="bi bi-calendar-date input-group-text"></i>
<input type="text" class="datepicker_input form-control" placeholder="Watch date" aria-label="Watch date" name="watchDate" id="watchDate" required>
<div class="invalid-feedback" id="watchDateValidationRequiredErrorMessage" style="padding-bottom: 0;margin-bottom: 0">
Watch date is required!
</div>
<div class="invalid-feedback" id="watchDateValidationFormatErrorMessage" style="padding-bottom: 0;margin-bottom: 0">
Watch date format is invalid!
</div>
<input type="number" class="form-control" name="personalRating" placeholder="Personal Rating" min="1" max="10" required style="margin-top: 1rem">
</div>
<div class="modal-footer">
<button type="submit" class="btn btn-primary">Log movie</button>
<div class="fw-light" id="ratingStars"
style="color: rgb(255, 193, 7);
font-size: 1.5rem;
margin-top: 0.5rem;
cursor:pointer;">
<span id="ratingStarsSpan">
{% for i in 1..10 %}
<i class="bi bi-star" id="ratingStar{{ i }}" onclick="updateRatingStars(this)"></i>
{% endfor %}
</span>
</div>
</form>
</div>
<div class="modal-footer">
<button type="submit" class="btn btn-primary" onclick="logMovie()">Log movie</button>
</div>
</div>
</div>
</div>
Expand Down
Loading

0 comments on commit 6edb587

Please sign in to comment.