Initial commit

This commit is contained in:
2021-09-16 20:27:51 +08:00
commit 5ed6195cc1
41 changed files with 3429 additions and 0 deletions

13
views/404.blade.php Normal file
View File

@ -0,0 +1,13 @@
@extends('layout.master')
@section('title')
404 Not Found -
@endsection
@section('header')
@parent
@endsection
@section('content')
<h1>404 Not Found</h1>
@endsection

0
views/cache/.gitkeep vendored Normal file
View File

View File

@ -0,0 +1,5 @@
<div class="footer">
<div class="container">
<h4 class="text-secondary">Blog App</h4>
</div>
</div>

View File

@ -0,0 +1,30 @@
<div class="header">
<div class="container">
@section('header')
<h4><a href="/" class="title text-dark">Blog App</a></h4>
@show
@if(isset($_SESSION['is_auth']))
<form method="POST" action="/user/logout" class="float-right">
<input type="hidden" name="_token" value="{{ $_SESSION['_token'] }}">
<button type="submit" class="btn btn-dark">Logout</button>
</form>
<div class="float-right">
<a href="/post/create" class="post-create btn btn-success">New Post</a>
</div>
@else
@if(! preg_match('/\/register$/', $_SERVER['REQUEST_URI']))
<div class="float-right">
<a href="/user/register" class="register btn btn-info">Register</a>
</div>
@endif
@if(! preg_match('/\/login$/', $_SERVER['REQUEST_URI']))
<div class="float-right">
<a href="/user/login" class="login btn btn-light">Login</a>
</div>
@endif
@endif
<div class="float-right">
<input type="text" placeholder="Search title ..." id="search" class="search form-control" value="{{ isset($keyword) ? urldecode($keyword) : '' }}">
</div>
</div>
</div>

View File

@ -0,0 +1,46 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>@yield('title')Blog App</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.0/css/bootstrap.min.css" integrity="sha384-9gVQ4dYFwwWSjIDZnLEWnxCjeSWFphJiwGPXr1jddIhOegiu1FwO5qRGvFXOdJZ4" crossorigin="anonymous">
<link rel="stylesheet" href="/css/main.css">
<script defer src="https://use.fontawesome.com/releases/v5.0.13/js/all.js" integrity="sha384-xymdQtn1n3lH2wcu0qhcdaOpQwyoarkgLVxC/wZ5q7h9gHtxICrpcaSUfygqZGOe" crossorigin="anonymous"></script>
</head>
<body>
@include('layout.header')
<div class="container">
<div class="row">
<div class="main col">
@if(isset($errors))
<ul class="errors alert alert-danger">
@foreach($errors as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
@endif
@if(isset($messages))
<ul class="messages alert alert-info">
@foreach($messages as $message)
<li>{{ $message }}</li>
@endforeach
</ul>
@endif
@yield('content')
@yield('comments')
</div>
<div class="sidebar col-lg-3">
@yield('sidebar')
</div>
</div>
</div>
@include('layout.footer')
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.0/umd/popper.min.js" integrity="sha384-cs/chFZiN24E4KMATLdqdvsezGxaGsi4hLGOzlXwp5UZB1LY//20VyM2taTB4QvJ" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.0/js/bootstrap.min.js" integrity="sha384-uefMccjFJAIv6A+rW+L4AHf99KvxDjWSu1z9VI8SKNVmz4sk7buKt/6v9KI65qnm" crossorigin="anonymous"></script>
<script src="/js/main.js"></script>
</body>
</html>

View File

@ -0,0 +1,19 @@
@if(isset($_SESSION['is_auth']))
<img src="https://www.gravatar.com/avatar/{{ md5(strtolower(trim($_SESSION['email']))) }}?s=50&d=mm&r=pg" class="avatar">
<a href="/user/settings" class="user-setting" title="Settings">
<i class="fas fa-cog gear"></i>
</a>
<h4>
<a href="/user/{{ $_SESSION['username'] }}" class="user-info">
{{ $_SESSION['username'] }}
</a>
</h4>
@endif
@if(isset($tags))
<ul class="tags">
@foreach($tags as $tag)
<li><a href="/tag/{{ $tag->id }}">{{ $tag->keyword }}</a> ({{ $tag->num_of_posts }})</li>
@endforeach
</ul>
@endif

View File

@ -0,0 +1,23 @@
@extends('layout.master')
@section('title')
Password Reset -
@endsection
@section('content')
<form method="POST" action="">
<input type="hidden" name="_token" value="{{ $_SESSION['_token'] }}">
<input type="hidden" name="id" value="{{ $_GET['id'] }}">
<input type="hidden" name="forget_token" value="{{ $_GET['forget_token'] }}">
<div class="form-group">
<label for="password">Password</label>
<input type="password" name="password" class="form-control" placeholder="Enter password">
</div>
<div class="form-group">
<label for="confirm-password">Confirmation</label>
<input type="password" name="confirm-password" class="form-control" placeholder="Enter password again">
</div>
<button type="submit" class="btn btn-primary">Reset</button>
</form>
@endsection

View File

@ -0,0 +1,16 @@
@extends('layout.master')
@section('title')
Password Reset -
@endsection
@section('content')
<form method="POST" action="">
<input type="hidden" name="_token" value="{{ $_SESSION['_token'] }}">
<div class="form-group">
<label for="email">Email</label>
<input type="email" name="email" class="form-control" placeholder="Enter email">
</div>
<button type="submit" class="btn btn-primary">Send</button>
</form>
@endsection

View File

@ -0,0 +1,3 @@
@extends('post.edit')
@section('submit') Publish @endsection

38
views/post/edit.blade.php Normal file
View File

@ -0,0 +1,38 @@
@extends('layout.master')
@section('content')
<form method="POST" action="">
<input type="hidden" name="_token" value="{{ $_SESSION['_token'] }}">
<div class="form-group">
<input type="text" class="form-control" name="title" placeholder="Enter title" maxlength="255" value="{{ $title ?? $post->title }}">
</div>
<div class="form-group">
<textarea id="source-content" class="form-control" name="content" rows="10">{{ $content ?? $post->content }}</textarea>
</div>
<div class="form-group row">
<label class="col-sm-1 col-form-label text-right">Tags: </label>
<div class="col-sm-11">
<input type="text" class="form-control" name="tags" placeholder="Separated by commas (,)" maxlength="255" value="{{ $tags ?? $post->tags }}">
</div>
</div>
<button type="submit" class="btn btn-primary float-right">@section('submit') Edit @show</button>
<button type="button" id="preview-post-btn" class="preview-post-btn btn btn-secondary float-right" data-toggle="modal" data-target="#preview-post">Preview</button>
</form>
<div class="modal fade" id="preview-post" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog modal-lg" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Preview</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body" id="preview-content">
</div>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
@endsection

View File

@ -0,0 +1,59 @@
@extends('layout.master')
@section('content')
<div class="posts">
@if(count($posts) == 0)
<h3 class="text-secondary">No content</h3>
@endif
@foreach($posts as $post)
<div>
<span class="text-secondary">{{ explode(' ', $post->create_at)[0] }}</span>
@if(isset($_SESSION['is_auth']) && $post->author == $_SESSION['username'])
<a href="/post/{{ $post->id }}/edit" class="text-primary">Edit</a>
<a href="#" class="text-danger" data-toggle="modal" data-target="#confirm-modal" data-action="/post/{{ $post->id }}/delete">Delete</a>
@endif
</div>
<h2 class="title">
<a href="/post/{{ $post->id }}">{!! isset($keyword) ? preg_replace('/' . preg_quote(e($keyword)) . '/i', '<span class="match">$0</span>', e($post->title)) : e($post->title) !!}</a>
</h2>
@endforeach
<ul class="pager">
@if($page > 1)
<li class="previous"><a href="{{ $pager_uri }}/{{ $page - 1 }}">&larr; Prev</a></li>
@endif
@if(! $is_last)
<li class="next"><a href="{{ $pager_uri }}/{{ $page + 1 }}">Next &rarr;</a></li>
@endif
</ul>
<div class="modal fade" id="confirm-modal" tabindex="-1" role="dialog" aria-labelledby="confirm-label" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="confirm-label">Confirmation</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
Are you sure you want to delete this post?
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">No</button>
<form method="POST" action="" id="delete-form">
<input type="hidden" name="_token" value="{{ $_SESSION['_token'] }}">
<button type="submit" class="btn btn-danger">Yes</button>
</form>
</div>
</div>
</div>
</div>
</div>
@endsection
@section('sidebar')
@include('layout.sidebar')
@endsection

139
views/post/show.blade.php Normal file
View File

@ -0,0 +1,139 @@
@extends('layout.master')
@section('title')
{{ $post->title }} -
@endsection
@section('content')
<h2>{{ $post->title }}</h2>
<div>
<span class="text-secondary">Published at: {{ $post->create_at }}</span>,
<span class="text-secondary">Author: <a href="/user/{{ $post->author }}" class="text-info">{{ $post->author }}</a></span>
@if(isset($_SESSION['is_auth']) && $post->author == $_SESSION['username'])
<a href="/post/{{ $post->id }}/edit" class="text-primary">Edit</a>
<a href="#" class="text-danger" data-toggle="modal" data-target="#confirm-modal">Delete</a>
<div class="modal fade" id="confirm-modal" tabindex="-1" role="dialog" aria-labelledby="confirm-label" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="confirm-label">Confirmation</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
Are you sure you want to delete this post?
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">No</button>
<form method="POST" action="/post/{{ $post->id }}/delete">
<input type="hidden" name="_token" value="{{ $_SESSION['_token'] }}">
<button type="submit" class="btn btn-danger">Yes</button>
</form>
</div>
</div>
</div>
</div>
@endif
</div>
<article id="content">
@markdown($post->content)
</article>
@if(count($tags))
<div class="tags text-right">
@foreach($tags as $key => $tag)
<a href="/tag/{{ $tag->id }}" class="text-info">{{ $tag->keyword }}</a>
@if($key < count($tags) - 1),@endif
@endforeach
</div>
@endif
@endsection
@section('comments')
<div class="comments">
@if(isset($comment_errors))
<ul class="errors alert alert-danger">
@foreach($comment_errors as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
@endif
@if(isset($_SESSION['is_auth']))
<form method="POST" action="/comment/create" class="comment-form">
<input type="hidden" name="_token" value="{{ $_SESSION['_token'] }}">
<input type="hidden" name="post_id" value="{{ $post->id }}">
<div class="form-group">
<textarea name="content" rows="1" class="form-control"></textarea>
</div>
<button type="submit" class="btn btn-primary float-right">Comment</button>
</form>
@endif
@if(count($comments))
<h3>{{ $post->num_of_comments }} {{ $post->num_of_comments > 1 ? 'comments' : 'comment' }}:</h3>
@foreach($comments as $comment)
<img src="https://www.gravatar.com/avatar/{{ md5(strtolower(trim($comment->email))) }}?s=50&d=mm&r=pg" class="avatar">
<div>
<h5>{{ $comment->author }}</h5>
<span class="text-secondary">{{ $comment->create_at }}</span>
@if(isset($_SESSION['is_auth']))
@if($comment->author == $_SESSION['username'])
<a href="#" class="text-primary" data-toggle="modal" data-target="#comment-edit-modal" data-action="/comment/{{ $comment->id }}/edit">Edit</a>
@endif
@if($post->author == $_SESSION['username'])
<a href="#" class="text-danger" data-toggle="modal" data-target="#comment-confirm-modal" data-action="/comment/{{ $comment->id }}/delete">Delete</a>
@endif
@endif
</div>
<p>{!! nl2br(e($comment->content)) !!}</p>
@endforeach
<div class="modal fade" id="comment-confirm-modal" tabindex="-1" role="dialog" aria-labelledby="confirm-label" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="comment-confirm-label">Confirmation</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
Are you sure you want to delete this comment?
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">No</button>
<form method="POST" action="" id="delete-form">
<input type="hidden" name="_token" value="{{ $_SESSION['_token'] }}">
<input type="hidden" name="post_id" value="{{ $post->id }}">
<button type="submit" class="btn btn-danger">Yes</button>
</form>
</div>
</div>
</div>
</div>
<div class="modal fade" id="comment-edit-modal" tabindex="-1" role="dialog" aria-labelledby="edit-label" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="comment-edit-label">Edit Comment</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<form method="POST" action="" id="comment-edit-form">
<input type="hidden" name="_token" value="{{ $_SESSION['_token'] }}">
<input type="hidden" name="post_id" value="{{ $post->id }}">
<div class="modal-body">
<div class="form-group">
<textarea name="content" rows="3" class="form-control"></textarea>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button>
<button type="submit" class="btn btn-primary">Edit</button>
</div>
</form>
</div>
</div>
</div>
@endif
</div>
@endsection

16
views/redirect.blade.php Normal file
View File

@ -0,0 +1,16 @@
@extends('layout.master')
@section('content')
<p>{{ $message }}</p>
<p>You will be redirected to homepage in <span id="sec">10</span> seconds.</p>
<script>
setInterval(function () {
var sec = document.getElementById('sec');
sec.textContent -= 1;
if (sec.textContent == 0) {
window.location = '/';
}
}, 1000);
</script>
@endsection

View File

@ -0,0 +1 @@
@extends('post.index')

View File

@ -0,0 +1,21 @@
@extends('layout.master')
@section('title')
Login -
@endsection
@section('content')
<form method="POST" action="/user/login">
<input type="hidden" name="_token" value="{{ $_SESSION['_token'] }}">
<div class="form-group">
<label for="username">Username</label>
<input type="text" name="username" class="form-control" placeholder="Enter username" value="{{$username ?? '' }}">
</div>
<div class="form-group">
<label for="password">Password</label>
<input type="password" name="password" class="form-control" placeholder="Enter password">
</div>
<button type="submit" class="btn btn-primary">Login</button>
<a href="/user/password/reset" class="text-info float-right">Forgot password?</a>
</form>
@endsection

View File

@ -0,0 +1,28 @@
@extends('layout.master')
@section('title')
Register -
@endsection
@section('content')
<form method="POST" action="">
<input type="hidden" name="_token" value="{{ $_SESSION['_token'] }}">
<div class="form-group">
<label for="username">Username</label>
<input type="text" name="username" class="form-control" placeholder="Enter username" value="{{ $username ?? '' }}">
</div>
<div class="form-group">
<label for="email">Email</label>
<input type="email" name="email" class="form-control" placeholder="Enter email" value="{{ $email ?? '' }}">
</div>
<div class="form-group">
<label for="password">Password</label>
<input type="password" name="password" class="form-control" placeholder="Enter password">
</div>
<div class="form-group">
<label for="confirm-password">Confirmation</label>
<input type="password" name="confirm-password" class="form-control" placeholder="Enter password again">
</div>
<button type="submit" class="btn btn-primary">Register</button>
</form>
@endsection

View File

@ -0,0 +1,62 @@
@extends('layout.master')
@section('title')
Settings -
@endsection
@section('content')
<img src="https://www.gravatar.com/avatar/{{ md5(strtolower(trim($_SESSION['email']))) }}?s=100&d=mm&r=pg" class="avatar">
<form method="POST" action="">
<input type="hidden" name="_token" value="{{ $_SESSION['_token'] }}">
<input type="hidden" name="id" value="{{ $_SESSION['id'] }}">
<table class="table">
<tbody>
<tr>
<th scope="row">Name:</th>
<td><input type="text" name="username" value="{{ $_SESSION['username'] }}" class="form-control"></td>
</tr>
<tr>
<th scope="row">E-mail:</th>
<td><input type="email" name="email" value="{{ $_SESSION['email'] }}" class="form-control"></td>
</tr>
<tr>
<th scope="row">Password:</th>
<td><input type="password" name="password" placeholder="Leave blank for no change" class="form-control"></td>
</tr>
<tr>
<th scope="row">Confirmation:</th>
<td><input type="password" name="confirm-password" placeholder="Leave blank for no change" class="form-control"></td>
</tr>
<tr>
<td></td>
<td><button type="submit" class="btn btn-primary float-right">Save</button></td>
</tr>
</tbody>
</table>
</form>
<a href="#" class="text-muted text-danger" data-toggle="modal" data-target="#account-delete-modal">Delete account</a>
<div class="modal fade" id="account-delete-modal" tabindex="-1" role="dialog" aria-labelledby="confirm-label" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="account-delete-label">Confirmation</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
Are you sure you want to delete your account?
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">No</button>
<form method="POST" action="/user/delete">
<input type="hidden" name="_token" value="{{ $_SESSION['_token'] }}">
<button type="submit" class="btn btn-danger">Yes</button>
</form>
</div>
</div>
</div>
</div>
@endsection