Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
2b0c3d2
Completed setting the empty project
comfortprince Oct 26, 2024
b1e7130
Created the Category model and its associated migrations
comfortprince Oct 26, 2024
955dfb3
Category Management and Navigation Enhancements
comfortprince Oct 26, 2024
29fc896
This update introduced a toggle button for the modal form on which ne…
comfortprince Oct 27, 2024
5254141
Category Management and Display
comfortprince Oct 27, 2024
36e2fab
Implemented Category Update Logic
comfortprince Oct 27, 2024
65351f8
Implemented the Category delete logic
comfortprince Oct 27, 2024
46f1dec
Created the tags migration
comfortprince Oct 28, 2024
eccf208
Tag Managment
comfortprince Oct 28, 2024
748e0af
Tag Management
comfortprince Oct 28, 2024
3f021f8
Tag Management
comfortprince Oct 28, 2024
b7e65ce
Tag Management
comfortprince Oct 28, 2024
50ea075
Tag Management
comfortprince Oct 28, 2024
a740f9d
Tag Management
comfortprince Oct 29, 2024
bbe9b34
Tag Management
comfortprince Oct 29, 2024
227cb92
Article Management
comfortprince Oct 29, 2024
7e785ad
feat: Add article creation functionality with form validation
comfortprince Oct 31, 2024
54f2075
feat: Fixed the image upload bug.
comfortprince Oct 31, 2024
f8f5ba8
wip: Begin implementation of store method in ArticleController
comfortprince Oct 31, 2024
7dc37c5
wip: Add tag association to article store method
comfortprince Oct 31, 2024
52063bc
feat: Complete article store method with image storage using Spatie I…
comfortprince Oct 31, 2024
9da10ef
feat: Complete editing blog name and logo.
comfortprince Oct 31, 2024
6451e56
refactor: Group article, tag, and category routes with prefix and aut…
comfortprince Nov 2, 2024
9e68abc
refactor: Add navigation slot in app layout for flexible navigation i…
comfortprince Nov 2, 2024
199f560
style: Refactor CSS and update app layout with Roboto font for headers
comfortprince Nov 3, 2024
19f200c
refactor: Update routes for landing page, about page, and specific ar…
comfortprince Nov 3, 2024
61f0175
feat: Add and style landing page with guest navigation template
comfortprince Nov 3, 2024
7361a9e
refactor: Update navigation and redirect dashboard to admin articles
comfortprince Nov 3, 2024
0449be8
feat: Add media collection setup for Article images
comfortprince Nov 4, 2024
f61a330
refactor: Add navigation slot to article creation view
comfortprince Nov 4, 2024
63e49e1
refactor: Dynamically display recent posts on article index view
comfortprince Nov 4, 2024
d3cf5f8
I got lazy and didn't want to craft a commit message
comfortprince Nov 5, 2024
91426d0
feat: Implement article deletion with media cleanup
comfortprince Nov 6, 2024
d41a4dc
Completed the beginner project.
comfortprince Nov 14, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
root = true

[*]
charset = utf-8
end_of_line = lf
indent_size = 4
indent_style = space
insert_final_newline = true
trim_trailing_whitespace = true

[*.md]
trim_trailing_whitespace = false

[*.{yml,yaml}]
indent_size = 2

[docker-compose.yml]
indent_size = 4
66 changes: 66 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
APP_NAME=Laravel
APP_ENV=local
APP_KEY=
APP_DEBUG=true
APP_TIMEZONE=UTC
APP_URL=http://localhost

APP_LOCALE=en
APP_FALLBACK_LOCALE=en
APP_FAKER_LOCALE=en_US

APP_MAINTENANCE_DRIVER=file
# APP_MAINTENANCE_STORE=database

PHP_CLI_SERVER_WORKERS=4

BCRYPT_ROUNDS=12

LOG_CHANNEL=stack
LOG_STACK=single
LOG_DEPRECATIONS_CHANNEL=null
LOG_LEVEL=debug

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=temp
DB_USERNAME=root
DB_PASSWORD=

SESSION_DRIVER=database
SESSION_LIFETIME=120
SESSION_ENCRYPT=false
SESSION_PATH=/
SESSION_DOMAIN=null

BROADCAST_CONNECTION=log
FILESYSTEM_DISK=local
QUEUE_CONNECTION=database

CACHE_STORE=database
CACHE_PREFIX=

MEMCACHED_HOST=127.0.0.1

REDIS_CLIENT=phpredis
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379

MAIL_MAILER=log
MAIL_HOST=127.0.0.1
MAIL_PORT=2525
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null
MAIL_FROM_ADDRESS="hello@example.com"
MAIL_FROM_NAME="${APP_NAME}"

AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
AWS_DEFAULT_REGION=us-east-1
AWS_BUCKET=
AWS_USE_PATH_STYLE_ENDPOINT=false

VITE_APP_NAME="${APP_NAME}"
11 changes: 11 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
* text=auto eol=lf

*.blade.php diff=html
*.css diff=css
*.html diff=html
*.md diff=markdown
*.php diff=php

/.github export-ignore
CHANGELOG.md export-ignore
.styleci.yml export-ignore
22 changes: 22 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/.phpunit.cache
/node_modules
/public/build
/public/hot
/public/storage
/storage/*.key
/storage/pail
/vendor
.env
.env.backup
.env.production
.phpactor.json
.phpunit.result.cache
Homestead.json
Homestead.yaml
auth.json
npm-debug.log
yarn-error.log
/.fleet
/.idea
/.vscode
/.zed
151 changes: 151 additions & 0 deletions app/Http/Controllers/ArticleController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
<?php

namespace App\Http\Controllers;

use App\Http\Requests\StoreArticleRequest;
use App\Http\Requests\UpdateArticleRequest;
use App\Models\Article;
use App\Models\Category;
use App\Models\Tag;
use Illuminate\Support\Facades\DB;
use Illuminate\Http\Request;

class ArticleController extends Controller
{
/**
* Display a listing of the resource.
*/
public function index()
{
$articles = Article::all();
return view("article.index", compact("articles"));
}

/**
* Show the form for creating a new resource.
*/
public function create()
{
$categories = Category::all();
$tags = Tag::all();
return view("article.create", compact("categories","tags"));
}

/**
* Store a newly created resource in storage.
*/
public function store(StoreArticleRequest $request)
{
$validated = $request->validated();
$article = new Article();
$article->title = $validated["title"];
$article->body = $validated["body"];
$article->category_id = $validated['category'];
$article->save();

$article->tags()->attach($validated['tags']);

if($request->hasFile('image')) {
$article->addMediaFromRequest('image')->toMediaCollection('article_images');
}

session()->flash('success','Successfully posted a new article.');

return redirect()->route('admin.articles.index');
}

/**
* Display the specified resource.
*/
public function show(string $id)
{
//
}

/**
* Show the form for editing the specified resource.
*/
public function edit(string $id)
{
$article = Article::findOrFail($id);
$article->load(['category', 'media', 'tags']);
$categories = Category::all();
$tags = Tag::all();
return view('article.edit', compact('article', 'tags','categories'));
}

/**
* Update the specified resource in storage.
*/
public function update(UpdateArticleRequest $request, string $id)
{


$article = Article::findOrFail($id);
$validated = $request->validated();

$article->title = $validated['title'];
$article->body = $validated['body'];
$article->category_id = $validated['category'];

$article->save();

$article->tags()->sync($validated['tags']);

$imageEditAction = $request->input("image_edit_action");

switch ($imageEditAction) {
case 'replace':
$article->clearMediaCollection('article_images');

if (request()->hasFile('image')) {
$article->addMediaFromRequest('image')->toMediaCollection('article_images');
}else{
$imgPath = $article->getFirstMedia('pending_article_images')->getPath();
$article->addMedia($imgPath)->toMediaCollection('article_images');
}

$article->clearMediaCollection('pending_article_images');
$article->image_edit_action = null;
$article->save();
break;

case 'keep':
$article->clearMediaCollection('pending_article_images');
$article->image_edit_action = null;
$article->save();
break;

case 'delete':
$article->clearMediaCollection('pending_article_images');
$article->clearMediaCollection('article_images');
$article->image_edit_action = null;
$article->save();
break;

default:
# code...
break;
}

session()->flash('success','Successfully updated the specified article.');

return redirect()->route('admin.articles.index');
}

/**
* Remove the specified resource from storage.
*/
public function destroy(string $id)
{
$article = Article::findOrFail($id);

DB::transaction(function () use ($article) {
$article->getFirstMedia('article_images')->delete();
$article->delete();
});

session()->flash('success','Successfully deleted an article');
return redirect()->route('admin.articles.index');
}
}
47 changes: 47 additions & 0 deletions app/Http/Controllers/Auth/AuthenticatedSessionController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<?php

namespace App\Http\Controllers\Auth;

use App\Http\Controllers\Controller;
use App\Http\Requests\Auth\LoginRequest;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\View\View;

class AuthenticatedSessionController extends Controller
{
/**
* Display the login view.
*/
public function create(): View
{
return view('auth.login');
}

/**
* Handle an incoming authentication request.
*/
public function store(LoginRequest $request): RedirectResponse
{
$request->authenticate();

$request->session()->regenerate();

return redirect()->intended(route('dashboard', absolute: false));
}

/**
* Destroy an authenticated session.
*/
public function destroy(Request $request): RedirectResponse
{
Auth::guard('web')->logout();

$request->session()->invalidate();

$request->session()->regenerateToken();

return redirect('/');
}
}
40 changes: 40 additions & 0 deletions app/Http/Controllers/Auth/ConfirmablePasswordController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?php

namespace App\Http\Controllers\Auth;

use App\Http\Controllers\Controller;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Validation\ValidationException;
use Illuminate\View\View;

class ConfirmablePasswordController extends Controller
{
/**
* Show the confirm password view.
*/
public function show(): View
{
return view('auth.confirm-password');
}

/**
* Confirm the user's password.
*/
public function store(Request $request): RedirectResponse
{
if (! Auth::guard('web')->validate([
'email' => $request->user()->email,
'password' => $request->password,
])) {
throw ValidationException::withMessages([
'password' => __('auth.password'),
]);
}

$request->session()->put('auth.password_confirmed_at', time());

return redirect()->intended(route('dashboard', absolute: false));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

namespace App\Http\Controllers\Auth;

use App\Http\Controllers\Controller;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;

class EmailVerificationNotificationController extends Controller
{
/**
* Send a new email verification notification.
*/
public function store(Request $request): RedirectResponse
{
if ($request->user()->hasVerifiedEmail()) {
return redirect()->intended(route('dashboard', absolute: false));
}

$request->user()->sendEmailVerificationNotification();

return back()->with('status', 'verification-link-sent');
}
}
Loading