Fait se qui qui a dans la to do list et du design

main
Dion Musliu ago%!(EXTRA string=10 months)
parent 949296395c
commit 6e251a9a77
  1. 25
      app/Http/Controllers/BlogController.php
  2. 1
      app/Models/Blog.php
  3. 1
      app/Models/User.php
  4. 1
      database/migrations/2014_10_12_000000_create_users_table.php
  5. 1
      database/migrations/2024_08_20_091442_create_blogs_table.php
  6. 2753
      package-lock.json
  7. 3
      package.json
  8. 6
      postcss.config.js
  9. 0
      public/img/blog_logo.webp
  10. 9
      public/img/create_icon.svg
  11. 2
      public/img/follow_icon.svg
  12. 8
      public/img/home_icon.svg
  13. BIN
      public/img/like_icon.png
  14. 3
      public/img/like_icon.svg
  15. 8
      public/img/profile_icon.svg
  16. 9
      public/img/register_icon.svg
  17. 2
      public/img/signin_icon.svg
  18. 8
      public/img/signout_icon.svg
  19. BIN
      public/img/test_logo.png
  20. BIN
      public/img/view_icon.png
  21. 5
      public/img/view_icon.svg
  22. 144
      resources/css/app.css
  23. 137
      resources/js/blog.js
  24. 4
      resources/views/auth/login.blade.php
  25. 4
      resources/views/auth/register.blade.php
  26. 4
      resources/views/auth/verify_email.blade.php
  27. 3
      resources/views/base/errors.blade.php
  28. 5
      resources/views/base/icon.blade.php
  29. 15
      resources/views/base/layout.blade.php
  30. 33
      resources/views/base/menu.blade.php
  31. 32
      resources/views/blog/create.blade.php
  32. 6
      resources/views/blog/list.blade.php
  33. 1
      resources/views/blog/modal_update.blade.php
  34. 67
      resources/views/blog/single.blade.php
  35. 27
      resources/views/blog/view.blade.php
  36. 34
      resources/views/layout.blade.php
  37. 4
      resources/views/user/profile.blade.php
  38. 24
      tailwind.config.js

@ -8,6 +8,7 @@
use GrahamCampbell\ResultType\Success;
use Illuminate\Support\Facades\Auth;
use Illuminate\Database\QueryException;
use Illuminate\Support\Facades\Storage;
class BlogController extends Controller
{
@ -42,10 +43,12 @@ public function like($id)
try {
$blog->likes()->attach(request()->user()->id);
} catch(QueryException $e) {
return response('', 400);
return redirect('/blog/' . $id)->withErrors([
"error" => "Blog already liked"
]);
}
return response('', 200);
return redirect('/blog/' . $id);
}
public function create()
@ -60,16 +63,31 @@ public function insert()
]);
$id = request()->user()->id;
$image = BlogController::getRequestImage();
$blog = Blog::create([
'title' => request('title'),
'containt' => request('containt'),
'epilog' => request('epilog'),
'image' => $image,
'user_id' => $id,
]);
return redirect('/blog/' . $blog->id);
}
private static function getRequestImage()
{
if(request()->hasFile('image'))
{
$hash = request()->file('image')->hashName();
request()->file('image')->store('public/images/blog');
return $hash;
}
else return "";
}
public function delete($id)
{
$blog = Blog::find($id);
@ -90,9 +108,12 @@ public function update($id)
if (!$blog) return response('', 404);
if (request()->user()->id != $blog->user->id) return response('', 401);
$image = BlogController::getRequestImage();
$blog->title = request('title');
$blog->containt = request('containt');
$blog->epilog = request('epilog');
if($image) $blog->image = $image;
$blog->save();
return response('', 200);

@ -17,6 +17,7 @@ class Blog extends Model
'title',
'containt',
'epilog',
'image',
'views',
'user_id'
];

@ -24,6 +24,7 @@ class User extends Authenticatable implements MustVerifyEmail
'username',
'name',
'description',
'image',
'email',
'password',
];

@ -18,6 +18,7 @@ public function up(): void
$table->string('description', 500)->nullable();
$table->string('email')->unique();
$table->timestamp('email_verified_at')->nullable();
$table->string('image')->nullable();
$table->string('password');
$table->rememberToken();
$table->timestamps();

@ -17,6 +17,7 @@ public function up(): void
$table->string('epilog', 350)->nullable();
$table->longText('containt')->nullable();
$table->unsignedBigInteger('views')->default(0);
$table->string('image')->nullable();
$table->unsignedBigInteger('user_id');
$table->timestamps();
$table->foreign('user_id')->references('id')->on('users');

2753
package-lock.json generated

File diff suppressed because it is too large Load Diff

@ -6,8 +6,11 @@
"build": "vite build"
},
"devDependencies": {
"autoprefixer": "^10.4.20",
"axios": "^1.6.4",
"laravel-vite-plugin": "^1.0.0",
"postcss": "^8.4.41",
"tailwindcss": "^3.4.10",
"vite": "^5.0.0"
}
}

@ -0,0 +1,6 @@
export default {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
}

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 23 KiB

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<rect x="0" fill="none" width="24" height="24"/>
<g>
<path d="M21 14v5c0 1.105-.895 2-2 2H5c-1.105 0-2-.895-2-2V5c0-1.105.895-2 2-2h5v2H5v14h14v-5h2z"/>
<path d="M21 7h-4V3h-2v4h-4v2h4v4h2V9h4"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 424 B

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M3.691 8.507c0 2.847 1.582 5.29 3.806 5.29 2.223 0 3.803-2.443 3.803-5.29 0-2.846-1.348-4.51-3.803-4.51-2.456 0-3.806 1.664-3.806 4.51zM1.326 19.192c.82.537 2.879.805 6.174.805 3.295 0 5.353-.268 6.174-.804a.5.5 0 0 0 .225-.453c-.152-2.228-2.287-3.343-6.403-3.343-4.117 0-6.249 1.115-6.395 3.344a.5.5 0 0 0 .225.451zM18 17a1 1 0 0 1-1-1v-3h-3a1 1 0 1 1 0-2h3V8a1 1 0 1 1 2 0v3h3a1 1 0 1 1 0 2h-3v3a1 1 0 0 1-1 1z" fill="#000000"/></svg>

After

Width:  |  Height:  |  Size: 705 B

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<rect x="0" fill="none" width="24" height="24"/>
<g>
<path d="M22 9L12 1 2 9v2h2v10h5v-4c0-1.657 1.343-3 3-3s3 1.343 3 3v4h5V11h2V9z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 363 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

@ -0,0 +1,3 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 1024 1024" class="icon" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M725.333333 192c-89.6 0-168.533333 44.8-213.333333 115.2C467.2 236.8 388.266667 192 298.666667 192 157.866667 192 42.666667 307.2 42.666667 448c0 253.866667 469.333333 512 469.333333 512s469.333333-256 469.333333-512c0-140.8-115.2-256-256-256z" fill="#F44336" /></svg>

After

Width:  |  Height:  |  Size: 518 B

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<rect x="0" fill="none" width="24" height="24"/>
<g>
<path d="M12 2C6.477 2 2 6.477 2 12s4.477 10 10 10 10-4.477 10-10S17.523 2 12 2zm0 18.5c-4.694 0-8.5-3.806-8.5-8.5S7.306 3.5 12 3.5s8.5 3.806 8.5 8.5-3.806 8.5-8.5 8.5zm0-8c-3.038 0-5.5 1.728-5.5 3.5s2.462 3.5 5.5 3.5 5.5-1.728 5.5-3.5-2.462-3.5-5.5-3.5zm0-.5c1.657 0 3-1.343 3-3s-1.343-3-3-3-3 1.343-3 3 1.343 3 3 3z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 601 B

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<rect x="0" fill="none" width="24" height="24"/>
<g>
<circle cx="15" cy="8" r="4"/>
<path d="M15 20s8 0 8-2c0-2.4-3.9-5-8-5s-8 2.6-8 5c0 2 8 2 8 2zM6 10V7H4v3H1v2h3v3h2v-3h3v-2z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 409 B

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" id="sign-in" class="icon glyph"><path d="M20,22H10a2,2,0,0,1-2-2V16a1,1,0,0,1,2,0v4H20V4H10V8A1,1,0,0,1,8,8V4a2,2,0,0,1,2-2H20a2,2,0,0,1,2,2V20A2,2,0,0,1,20,22Z" style="fill:#231f20"></path><path d="M17,13H3a1,1,0,0,1,0-2H17a1,1,0,0,1,0,2Z" style="fill:#231f20"></path><path d="M13,17a1,1,0,0,1-.71-.29,1,1,0,0,1,0-1.42L15.59,12l-3.3-3.29a1,1,0,1,1,1.42-1.42l4,4a1,1,0,0,1,0,1.42l-4,4A1,1,0,0,1,13,17Z" style="fill:#231f20"></path></svg>

After

Width:  |  Height:  |  Size: 645 B

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<rect x="0" fill="none" width="24" height="24"/>
<g>
<path d="M16 17v2c0 1.105-.895 2-2 2H5c-1.105 0-2-.895-2-2V5c0-1.105.895-2 2-2h9c1.105 0 2 .895 2 2v2h-2V5H5v14h9v-2h2zm2.5-10.5l-1.414 1.414L20.172 11H10v2h10.172l-3.086 3.086L18.5 17.5 24 12l-5.5-5.5z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 486 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.4 KiB

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="12" cy="12" r="3" stroke="#33363F" stroke-width="2"/>
<path d="M21 12C21 12 20 4 12 4C4 4 3 12 3 12" stroke="#33363F" stroke-width="2"/>
</svg>

After

Width:  |  Height:  |  Size: 376 B

@ -1,139 +1,27 @@
:root {
--font-familly: "Ubuntu Mono";
@tailwind base;
@tailwind components;
@tailwind utilities;
@layer utilities {
/* Hide scrollbar for Chrome, Safari and Opera */
.no-scrollbar::-webkit-scrollbar {
display: none;
}
/* Hide scrollbar for IE, Edge and Firefox */
.no-scrollbar {
-ms-overflow-style: none; /* IE and Edge */
scrollbar-width: none; /* Firefox */
}
}
::-webkit-scrollbar {
width: 0 !important
:root {
--font-familly: "Ubuntu Mono";
}
body {
padding: 0;
margin: 0;
display: flex;
flex-direction: column;
align-items: center;
height: 100vh;
width: 100%;
font-family: var(--font-familly);
}
a {
padding: 0;
margin: 0;
color: inherit;
text-decoration: none;
}
button {
padding: 0;
margin: 0;
font-family: var(--font-familly);
}
input {
padding: 0;
margin: 0;
font-family: var(--font-familly);
}
main {
padding-top: 20px;
width: 100%;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
}
.menu {
color: white;
width: 100%;
display: flex;
justify-content: space-between;
align-items: center;
height: 100px;
background-color: rgb(36, 30, 30);
border-bottom: 1px solid black;
}
.menu a {
height: 100%;
display: flex;
justify-content: center;
align-items: center;
}
.brand {
height: 80%;
margin-left: 30px;
}
.menu-links {
display: flex;
width: fit-content;
margin-right: 30px;
}
.menu-link {
list-style: none;
padding: 25px;
}
.menu-link a {
font-size: 30px;
}
.blogs-block {
width: 60%;
margin:auto;
padding: 20px;
display: flex;
flex-direction: column;
}
.blog-view {
display: grid;
grid-template-columns: 0.5fr 0.5fr 1fr;
align-items: center;
border: 2px solid black;
border-radius: 10px;
margin-top: 10px;
margin-bottom: 10px;
padding-left: 20px;
padding-bottom: 10px;
}
.blog-title a {
padding-left: 10px;
}
.blog-title a h1 {
padding: 0;
margin: 0;
}
.blog-stats {
padding-top: 15px;
width: 60%;
display: flex;
align-items:flex-start;
justify-content: space-around;
font-size: 15px;
}
.blog-stats img {
height: 20px;
}
.info-block {
width: 20% ;
display: flex;
align-items: center;
justify-content: space-evenly;
}
.md-content {
font-family: "Courier Prime";
width: 60%;
}

@ -1,79 +1,96 @@
import './bootstrap';
function addEvent(btn, func) {
if(btn) func(btn);
}
window.addEventListener("DOMContentLoaded", () => {
let modal = document.querySelector('#modal-update');
let openModalBtn = document.querySelector("#open-modal");
let closeModalBtn = document.querySelector(".close-modal");
let deleteBlogBtn = document.querySelector(".btn-blog-delete");
let updateBlogBtn = document.querySelector(".btn-blog-update");
let likeBtn = document.querySelector(".btn-like");
let followBtn = document.querySelector(".btn-follow");
let closeModalBtn = document.querySelector("#close-modal");
let deleteBlogBtn = document.querySelector("#btn-blog-delete");
let updateBlogBtn = document.querySelector("#btn-blog-update");
let likeBtn = document.querySelector("#btn-like");
let followBtn = document.querySelector("#btn-follow");
followBtn.addEventListener("click", (e) => {
e.preventDefault();
let id = e.target.getAttribute("data-id");
let token = document.querySelector('input[name=_token]').value;
fetch(`/follow/${id}`, {
method: "POST",
headers: {
"X-CSRF-Token": token
}
}).then((res) => {
if (res.status === 400) alert("Couldn't follow this user");
//else window.location.href = "/profile/" + id;
addEvent(followBtn, (btn) => {
btn.addEventListener("click", (e) => {
e.preventDefault();
let id = e.target.getAttribute("data-id");
let token = document.querySelector('input[name=_token]').value;
fetch(`/follow/${id}`, {
method: "POST",
headers: {
"X-CSRF-Token": token
}
}).then((res) => {
if (res.status === 400) alert("Couldn't follow this user");
//else window.location.href = "/profile/" + id;
});
});
});
likeBtn.addEventListener("click", (e) => {
e.preventDefault();
let id = e.target.getAttribute("data-id");
let token = document.querySelector('input[name=_token]').value;
fetch(`/blog/like/${id}`, {
method: "POST",
headers: {
"X-CSRF-Token": token
}
}).then((res) => {
if (res.status === 400) alert("Blog already liked");
else window.location.href = "/blog/" + id;
addEvent(likeBtn, (btn) => {
btn.addEventListener("click", (e) => {
e.preventDefault();
let id = document.querySelector(".btn-like").getAttribute("data-id");
let token = document.querySelector('input[name=_token]').value;
fetch(`/blog/like/${id}`, {
method: "POST",
headers: {
"X-CSRF-Token": token
}
}).then((res) => {
if (res.status === 400) alert(res.value);
else window.location.href = "/blog/" + id;
});
});
});
openModalBtn.addEventListener("click", (e) => {
modal.showModal();
addEvent(openModalBtn, (btn) => {
btn.addEventListener("click", (e) => {
modal.showModal();
});
});
closeModalBtn.addEventListener("click", (e) => {
modal.close();
addEvent(closeModalBtn, (btn) => {
btn.addEventListener("click", (e) => {
modal.close();
});
});
updateBlogBtn.addEventListener("click", (e) => {
e.preventDefault();
let id = e.target.getAttribute("data-id");
let token = document.querySelector('input[name=_token]').value;
let form = document.querySelector('.update-form');
let formData = new FormData(form);
fetch(`/blog/${id}`, {
method: "POST",
headers: {
"X-CSRF-Token": token
},
body: formData
}).then((res) => {
window.location.href = "/blog/" + id;
addEvent(updateBlogBtn, (btn) => {
btn.addEventListener("click", (e) => {
e.preventDefault();
let id = e.target.getAttribute("data-id");
let token = document.querySelector('input[name=_token]').value;
let form = document.querySelector('.update-form');
let formData = new FormData(form);
fetch(`/blog/${id}`, {
method: "POST",
headers: {
"X-CSRF-Token": token
},
body: formData
}).then((res) => {
window.location.href = "/blog/" + id;
});
});
});
deleteBlogBtn.addEventListener("click", (e) => {
e.preventDefault();
let id = e.target.getAttribute("data-id");
let token = document.querySelector('input[name=_token]').value;
fetch(`/blog/${id}`, {
method: "DELETE",
headers: {
"X-CSRF-Token": token
}
}).then((res) => {
window.location.href = "/blogs"
addEvent(deleteBlogBtn, (btn) => {
btn.addEventListener("click", (e) => {
e.preventDefault();
let id = e.target.getAttribute("data-id");
let token = document.querySelector('input[name=_token]').value;
fetch(`/blog/${id}`, {
method: "DELETE",
headers: {
"X-CSRF-Token": token
}
}).then((res) => {
window.location.href = "/blogs"
});
});
});
})

@ -1,6 +1,6 @@
@extends('layout')
@extends('base.layout')
@section('body')
@section('content')
<h1>Login</h1>
<form action="/login" method="post">
@csrf

@ -1,6 +1,6 @@
@extends('layout')
@extends('base.layout')
@section('body')
@section('content')
<h1>Register</h1>
<form action="/register" method="post">
@csrf

@ -1,6 +1,6 @@
@extends('layout')
@extends('base.layout')
@section('body')
@section('content')
<div>
<h1>Email verification</h1>

@ -0,0 +1,3 @@
@foreach($errors->all() as $key => $error)
<p>{{ $error }}</p>
@endforeach

@ -0,0 +1,5 @@
<li class="flex justify-center mb-5">
<a href="{{ $link }}">
<img class="size-12" src="/img/{{ $icon }}">
</a>
</li>

@ -0,0 +1,15 @@
<!DOCTYPE html>
<html lang="en" class="">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="https://fonts.googleapis.com/css2?family=Courier+Prime:ital,wght@0,400;0,700;1,400;1,700&family=Ubuntu+Mono:ital,wght@0,400;0,700;1,400;1,700&display=swap" rel="stylesheet">
<title>BlogBuntu</title>
@vite('resources/css/app.css')
</head>
<body class="w-full flex p-0 m-0 bg-white dark:bg-black text-black dark:text-white">
@include('base.menu')
@include('base.errors')
@yield("content")
</body>
</html>

@ -0,0 +1,33 @@
<nav class="flex flex-col justify-between w-fit h-screen bg-white border-black pb-5 px-3
dark:bg-black border-r dark:border-white">
<a href="/" class="w-full flex justify-center mb-12">
<img class="size-[6rem] mx-auto" src="/img/blog_logo.webp">
</a>
<ul class="flex flex-col w-full">
@if(request()->user())
@include('base.icon', [
"icon" => "create_icon.svg",
"link" => "/blog/create"
])
@endif
@if(request()->user())
@include('base.icon', [
"icon" => "profile_icon.svg",
"link" => "/myprofile"
])
@include('base.icon', [
"icon" => "signout_icon.svg",
"link" => "/logout"
])
@else
@include('base.icon', [
"icon" => "register_icon.svg",
"link" => "/register"
])
@include('base.icon', [
"icon" => "signin_icon.svg",
"link" => "/login"
])
@endif
</ul>
</nav>

@ -1,13 +1,23 @@
@extends('layout')
@extends('base.layout')
@section('body')
<h1>Create a blog</h1>
<form action="/blog/" method="post">
@csrf
<p>Title</p><input name="title" type="text" value="{{ old('title') }}">
<p>Epilog</p><textarea name="epilog" type="text">{{ old('epilog') }}</textarea>
<p>Content</p><textarea name="containt" type="text">{{ old('containt') }}</textarea>
<br>
<input type="submit">
</form>
@section('content')
<div class="w-full flex justify-center items-center">
<div class="w-2/3 p-10 border border-black dark:border-white rounded-lg">
<h1 class="text-6xl font-bold pb-3 mb-5 border-b border-black dark:border-white">Create a blog</h1>
<form action="/blog/" method="post" class="flex flex-col items-center">
<div class="grid grid-cols-4 w-full">
<p class="mr-">Title :</p><input class="border border-gray-300 rounded-lg col-span-3 mb-5 p-2"
name="title" type="text" value="{{ old('title') }}">
<p>Image (Optional):</p><input class="border border-gray-300 rounded-lg col-span-3 mb-5 p-2"
name="image" type="file" value="{{ old('image') }}">
<p>Epilog (Optional):</p><textarea class="border border-gray-300 rounded-lg col-span-3 mb-5 p-2"
name="epilog" type="text">{{ old('epilog') }}</textarea>
<p>Content (Optional):</p><textarea class="border border-gray-300 rounded-lg col-span-3 mb-5 p-2"
name="containt" type="text">{{ old('containt') }}</textarea>
</div>
<input type="submit" class="rounded-lg bg-blue-500 text-white p-2 w-fit">
@csrf
</form>
</div>
</div>
@endsection

@ -1,7 +1,7 @@
@extends('layout')
@extends('base.layout')
@section('body')
<div class="blogs-block">
@section('content')
<div class="w-full mx-2 grid grid-cols-2">
@foreach($blogs as $blog)
@include('blog.view')
@endforeach

@ -3,6 +3,7 @@
<form class="update-form">
@csrf
<p>Title</p><input name="title" type="text" value="{{ old('title') ? old('title') : $blog->title }}">
<p>Image</p><input name="image" type="file" value="{{ old('image') ? old('image') : $blog->image }}">
<p>Epilog</p><textarea name="epilog" type="text">{{ old('epilog') ? old('epilog') : $blog->epilog }}</textarea>
<p>Content</p><textarea name="containt" type="text">{{ old('containt') ? old('containt') : $blog->containt }}</textarea>
<br>

@ -1,28 +1,47 @@
@extends('layout')
@extends('base.layout')
@section('body')
@section('content')
@vite('resources/js/blog.js')
@if(request()->user() && $blog->user->id == request()->user()->id)
<button id="open-modal">Update</button>
<form class="delete-form">
@csrf
<button class="btn btn-blog-delete" data-id="{{$blog->id}}">Delete</button>
</form>
@include('blog.modal_update')
@else
@endif
@csrf
<button class="btn-like" data-id="{{$blog->id}}">Like</button>
<button class="btn-follow" data-id="{{$blog->user->id}}">Follow</button>
<h1>{{ $blog->title }}</h1>
<a href="/profile/{{ $blog->user->id }}"><h3>by {{ $blog->user->username }}</h3></a>
<p>{{ $blog->epilog }}</p>
<p>Views : {{ $blog->views }}</p>
<p>Likes : {{ $blog->likes()->count() }}</p>
@if($blog->containt)
<div class="md-content">
{!! html_entity_decode(app(Spatie\LaravelMarkdown\MarkdownRenderer::class)->toHtml($blog->containt)) !!}
<div class="w-full h-screen overflow-y-auto">
<div class="w-full flex flex-col pt-10 items-center px-[230px]">
<div class="w-full flex justify-between">
@csrf
<div>
@if(request()->user() && $blog->user->id == request()->user()->id)
<button id="open-modal">Update</button>
<button id="btn-blog-delete" data-id="{{$blog->id}}">Delete</button>
@include('blog.modal_update')
@else
<button id="btn-follow" data-id="{{$blog->user->id}}">Follow</button>
@endif
</div>
<div class="flex">
<div class="flex justify-around items-center mr-5">
<p class="text-lg">{{ $blog->views }} views</p>
</div>
<div class="flex justify-around items-center bg-gray-200 dark:bg-gray-800 px-3 py-1 rounded-lg">
<p class="text-lg mr-2">{{ $blog->likes()->count() }}</p>
<button id="btn-like" data-id="{{$blog->id}}"><img class="w-[30px]" src="/img/like_icon.svg"></button>
</div>
</div>
</div>
<div class="w-full flex flex-col items-center">
<div class="w-full flex items-end justify-center border-b border-black pb-5">
<p class="text-8xl">{{ $blog->title }}</p>
<p class="pl-10 text-3xl">by</p>
<a class="pl-3 text-3xl" href="/profile/{{ $blog->user->id }}">{{ $blog->user->username }}</a>
</div>
@if($blog->image)
<img class="h-[250px] w-min w-max-[445px] mx-auto my-5"
src="{{ asset('storage/images/blog/' . $blog->image) }}" alt="{{ $blog->image }}">
@endif
<p class="w-full px-[80px] py-10 italic">{{ $blog->epilog }}</p>
</div>
@if($blog->containt)
<div class="md-content">
{!! html_entity_decode(app(Spatie\LaravelMarkdown\MarkdownRenderer::class)->toHtml($blog->containt)) !!}
</div>
@endif
</div>
@endif
</div>
@endsection

@ -1,15 +1,22 @@
<div class="blog-view">
<div class="blog-title">
<a href="/blog/{{ $blog->id }}"><h1>{{ $blog->title }}</h1></a>
<a href="/profile/{{ $blog->user->id }}">by {{ $blog->user->username }}</a>
<div class="grid grid-cols-3 w-full bg-white dark:bg-black hover:bg-gray-300 dark:hover:bg-gray-900 h-fit rounded-xl p-2 mt-5">
<a class="row-span-2 m-auto h-[150px] w-[266px] w-max-[266px] bg-black dark:bg-white rounded-xl" href="/blog/{{ $blog->id }}">
@if($blog->image)
<img class="h-[150px] w-min w-max-[266px] m-auto"
src="{{ asset('storage/images/blog/' . $blog->image) }}" alt="{{ $blog->image }}">
@endif
</a>
<div class="container h-full flex items-center">
<a href="/blog/{{ $blog->id }}" class="text-2xl mr-3">{{ $blog->title }}</a>
<a href="/profile/{{ $blog->user->id }}" class="text-lg">by {{ $blog->user->username }}</a>
</div>
<div class="blog-stats">
<div class="info-block">
<img src="/img/view_icon.png"><p>{{ $blog->views }}</p>
<div class="flex justify-around items-center">
<div class="flex justify-around items-center">
<p class="text-lg">{{ $blog->views }} views</p>
</div>
<div class="info-block">
<img src="/img/like_icon.png"><p>{{ $blog->likes()->count() }}</p>
<div class="flex justify-around items-center bg-gray-200 dark:bg-gray-800 px-3 py-1 rounded-lg">
<p class="text-lg mr-2">{{ $blog->likes()->count() }}</p>
<img class="w-[30px]" src="/img/like_icon.svg">
</div>
</div>
<p>{{ $blog->epilog }}</p>
<a class="w-full col-span-2" href="/blog/{{ $blog->id }}">{{ $blog->epilog }}</a>
</div>

@ -1,34 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="https://fonts.googleapis.com/css2?family=Courier+Prime:ital,wght@0,400;0,700;1,400;1,700&family=Ubuntu+Mono:ital,wght@0,400;0,700;1,400;1,700&display=swap" rel="stylesheet">
<title>Document</title>
@vite('resources/css/app.css')
</head>
<body>
<nav class="menu">
<a href="/"><img class="brand" src="/img/test_logo.webp"></a>
<ul class="menu-links">
@if(request()->user())
<li class="menu-link"><a href="/blog/create">Create a blog</a></li>
@endif
<li class="menu-link"><a href="/blogs">Blogs</a></li>
@if(request()->user())
<li class="menu-link"><a href="/myprofile">Profile</a></li>
<li class="menu-link"><a href="/logout">Logout</a></li>
@else
<li class="menu-link"><a href="/register">Register</a></li>
<li class="menu-link"><a href="/login">Login</a></li>
@endif
</ul>
</nav>
@foreach($errors->all() as $key => $error)
<p>{{ $error }}</p>
@endforeach
<main>
@yield("body")
</main>
</body>
</html>

@ -1,6 +1,6 @@
@extends('layout')
@extends('base.layout')
@section('body')
@section('content')
@vite('resources/js/user.js')
<h1>{{ $user->username }}</h1>
<p>Name : {{ $user->name }}</p>

@ -0,0 +1,24 @@
/** @type {import('tailwindcss').Config} */
export default {
darkMode: 'selector',
content: [
"./resources/**/*.blade.php",
"./resources/**/*.js",
"./resources/**/*.vue",
],
theme: {
screens: {
'tablet': '640px',
// => @media (min-width: 640px) { ... }
'laptop': '1024px',
// => @media (min-width: 1024px) { ... }
'desktop': '1280px',
// => @media (min-width: 1280px) { ... }
},
extend: {},
},
plugins: [],
}
Loading…
Cancel
Save