ক্লাস নং-২০ (পার্ট-১২)-dynamic class-show, edit, delete, dynamic single invoice, and many more.
আজকের ক্লাসে আমাদের লারাভেল LMS project এর বেশ কিছু কাজ দেওয়া হয়েছে যেগুলো আমাদের কে update করতে হবে।
--course dynamically class show
--single class-view
--dynamically course delete
--course attendance form
--individual invoice show
and many more.
এবং আমাদের course table এ আরেকটা columns add করা হয়েছে সেটা হলো slug এবং এর জন্য databaseseeder এউ course slug টা update করা হয়েছে। এবং আজকের ক্লাসের ওপরের কাজ গুলো যেহেতু আমাদের homework ছিলো তাই githhub এ কোড গুলো পেয়ে যাবেন। আর কিভাবে আপনি এই কাজ টা সম্পূর্ন করবেন সেটা সম্পর্কে কিছু গাইডলাইন এই ব্লগে দেওয়া হবে।
তো এর জন্য প্রথমেই আপনি আপনার web.php file চলে যাবেন curriculam এর রাউট তৈরি করার জন্য এবং এটা একটা resource route হবে।resourse route কী সেটা সম্পর্কে নিচ্ছয় আপনার জানা আছে। route তৈরির কাজ শেষ এবার আমরা আমাদের note table এর ডেটা আপডেট করব।এবং সেখানে রিলেশন এর জন্য টেবিল সিলেক্ট করব যেহেতু আমাদের ক্লাসের এবং আমাদের lead এর নোট প্রয়োজন।
Schema::create('notes', function (Blueprint $table) {
$table->id();
$table->text('description');
$table->timestamps();
});
Schema::create('lead_note', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('note_id');
$table->unsignedBigInteger('lead_id');
$table->timestamps();
$table->foreign('note_id')->references('id')->on('notes')->onDelete('cascade');
$table->foreign('lead_id')->references('id')->on('leads')->onDelete('cascade');
});
Schema::create('curriculum_note', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('note_id');
$table->unsignedBigInteger('curriculum_id');
$table->timestamps();
$table->foreign('note_id')->references('id')->on('notes')->onDelete('cascade');
$table->foreign('curriculum_id')->references('id')->on('curriculums')->onDelete('cascade');
});
এখানে আমি কোড গুলো দিয়ে দিচ্ছি তারপরেও আপনি আমাদের গিটহাবে কোড পেয়ে যাবেন সেখান থেকে কোড গুলো চেক করে নেবেন।
এবার আমরা আমাদের course model এ যাব এবং সেখানে আমাদের নতুন করে যে কোর্সের slug use করা হলো সেটা এখানে $fillable এ দিয়ে দেব।
protected $fillable = [
'name',
'slug',
'description',
'price',
'user_id'
];
এবং আমাদের curriculum model এ রিলেশন গুলো চেক করে নেব।
protected $fillable = [
'name',
'week_day',
'class_time',
'end_date',
'course_id'
];
protected $table = 'curriculums';
use HasFactory;
public function homeworks()
{
return $this->hasMany(Homework::class);
}
public function attendances()
{
return $this->hasMany(Attendance::class);
}
public function notes() {
return $this->belongsToMany(Note::class, 'curriculum_note');
}
public function course()
{
return $this->belongsTo(Course::class);
}
এবং আমাদের Lead model এ রিলেশন তৈরি করব।
public function notes() {
return $this->belongsToMany(Note::class, 'lead_note');
}
আর যদি রিলেশন থাকে তাহলে এখানে 'lead_note' টা id হিসেবে দিয়ে দিব।ব্যাস আমাদের মডেল এর কাজ complete.
এবার আমাদের কাজ controller এ ।
প্রথমেই আসি courseController এ ।এখানে যদি আমাদের আগে থেকেই create,index,edit,delete function গুলো থাকে তাহলে ভাল নাহলে আমরা এখানে তৈরি করব।
public function index()
{
return view('course.index');
}
public function create()
{
return view('course.create');
}
public function edit($id)
{
return view('course.edit', [
'course_id' => $id,
]);
}
public function show($id)
{
return view('course.show',['id' => $id]);
}
এবার আসি আমাদের curriculum controller এ যেখানে আমরা মূলত আজকে কাজ টা করব।
public function show($id){
return view('course.curriculum.show',['id'=>$id]);
}
public function edit($id){
return view('course.curriculum.edit',['id'=>$id]);
}
এখানে আমরা আমাদের show & edit function টা দিয়ে দিলাম সাথে id পাঠিয়ে দিলাম ।যাতে করে ভিউ তে আমরা id ধরে ডেটা শো করাতে পারি।
এবার আসি আমাদের invoiceController এ এর আআগে আমরা যে invoice টা দেখিয়েছিলাম সেটাকে এবার মডিফাই করব তাই আমাদের invoicecontroller এর show function এর সব comment করে আমরা শুধু invoice এর একটা ভিউ রিটার্ন করব show function এর মধ্যে।
return view('user.invoice.show', [
'invoice_id' => $id,
]);
controller এর কাজ এখন পর্যন্ত complete
এখন আমরা আসব livewire এ ।
আমাদের dynamically কাজ গুলো যেহেতু সব frontend এ তাই এখানে আমাদের মোটামুটি রিলেটেড সব ফাইল গুলো নিয়েই কাজ করা হয়েছে। তাই ছোট খাট change গুলো করা হয়েছে তাই সব কোড এখানে শেয়ার করা গেল না তবে ।এখানে আমি ফাইলগুলোর নাম বলে দিচ্ছি আপনি আমাদের github এর কোডের সাথে আপনার কোড গুলো মিলিয়ে নেবেন।
Admission.php
CourseCreate.php
CourseShow.php
CurriculumEdit.php
CurriculumShow.php
LeadEdit.php
এই ফাইলগুলো মূলত এখানে মডিফাই করা হয়েছে।
তবে এখানে ২ টা ফাইল একেবারেই নতুন যেগুলো livewire থেকে আপনাকে তৈরি করে নিতে হবে।এরজন্য।
php artisan livewire:make CurriculumEdit
php artisan livewire:make CurriculumShow
আমাদের টার্মিনালে এই কোড রান করলেই আমাদের livewire component তৈরি হয়ে যাবে।
তাহলে এখন পর্যন্ত আমাদের model,controller,livewire-component,database,seeder,route এর কাজগুলো complete
এখন আমরা ভিউ নিয়ে কাজ করব।
প্রথমেই আসি course এ ।এবং এখানে আমরা প্রথমেই show.blade.php file টাকে মডিফাই করা কোড গুলো মিলিয়ে নিব। এরপর course এর মধ্যে curriculum নামের একটা folder make করব এবং এর মধ্যে।
edit.blade.php show.blade.php file make করে livewire এ id পাঠিয়ে দিব।
এরপরে আসি user এ এবং এর মধ্যে আমরা প্রথমেই invoice নামের একটা ফোল্ডার তৈরি করে নেব।এবং invoice এর মধ্যে। show.blade.php file make করে livewire এ id পাঠিয়ে দিব। livewire থেকে আমাদের invoice কে dynamic করার জন্য।
এবার আমরা আমদের livewire এ ব্যাক করে প্রথমেই আমরা যে দুইটা ফাইল তৈরি করলাম সে দুইটা ফাইলে কোড গুলো লিখবো।
curriculum-edit.blade.php
<div class="p-6">
<form wire:submit.prevent="curriculumUpdate">
<div class="mb-6">
@include('components.form-field', [
'name' => 'name',
'label' => 'Name',
'type' => 'text',
'placeholder' => 'Enter name',
'required' => 'required',
])
</div>
@include('components.wire-loading-btn')
</form>
</div>
curriculum-show.blade.php
<div class="mx-auto p-4 text-gray-800">
<h1 class="font-bold mb-2 underline">{{$curriculum->course->name}}</h1>
<p class="mb-4 italic">Price: ${{$curriculum->course->price}}</p>
<p class="pb-6">{{$curriculum->course->description}}</p>
<h2 class="font-bold mb-2">Class</h2>
<p class="text-gray-600 mb-4"><span>Name: </span>{{$curriculum->name}}</p>
<h2 class="font-bold mb-2">Students</h2>
<table class="w-full table-auto">
<tr>
<th class="border px-4 py-2 text-left">Name</th>
<th class="border px-4 py-2 text-left">Email</th>
<th class="border px-4 py-2 text-center">Attendance</th>
</tr>
@foreach ($curriculum->course->students as $student)
<tr>
<td class="border px-4 py-2">{{$student->name}}</td>
<td class="border px-4 py-2">{{$student->email}}</td>
<td class="border px-4 py-2">
<div class="flex items-center justify-center gap-4">
<a href="" class="py-2 px-3 bg-green-500 text-white">Present</a>
<a href="" class="py-2 px-3 bg-red-500 text-white">Absent</a>
</div>
</td>
</tr>
@endforeach
</table>
<h3 class="font-bold text-lg my-4">Notes</h3>
@if (count($notes)>0)
@foreach($notes as $note)
<div class="mb-4 border border-gray-100 p-4">{{$note->description}}</div>
@endforeach
@else
<p class="py-4 text-red-400">Not Found Any Note!</p>
@endif
<h4 class="font-bold mb-2">Add new note</h4>
<form wire:submit.prevent="addNote">
<div class="mb-4">
<textarea wire:model="note" class="lms-input" placeholder="Type note"></textarea>
</div>
<button class="lms-btn" type="submit">Save</button>
</form>
</div>
এবং এখানেই আমাদের students দের course এ enroll কৃত তথ্য এবং এখানে students attendance form make করা হয়েছে।
এবার আমাদের course-show.blade.php file এ কোড গুলো লিখবো যেভাবে আমাদের কোর্স শো করাতে চাই।
<div class="mx-auto p-4 text-gray-800">
<h1 class="font-bold mb-2 underline">{{$course->name}}</h1>
<p class="mb-4 italic">Price: ${{$course->price}}</p>
<p class="pb-6">{{$course->description}}</p>
<h2 class="font-bold mb-2">Classes</h2>
<table class="w-full table-auto">
<tr>
<th class="border px-4 py-2 text-left">Name</th>
<th class="border px-4 py-2 text-left">Actions</th>
</tr>
@foreach ($curriculums as $class)
<tr>
<td class="border px-4 py-2">{{$class->name}}</td>
<td class="border px-4 py-2">
<div class="flex items-center justify-center">
<a class="mr-1" href="{{route('class.edit',$class->id)}}">
@include('components.icons.edit')
</a>
<a class="mr-1" href="{{route('class.show', $class->id)}}">
@include('components.icons.eye')
</a>
<form class="ml-1" onsubmit="return confirm('Are you sure?');"
wire:submit.prevent="curriculamDelete({{$class->id}})">
<button type="submit">
@include('components.icons.trash')
</button>
</form>
</div>
</td>
</tr>
@endforeach
</table>
</div>
এবং আমাদের course-index file এ যেভাবে কোর্স দেখাতে চাই সেটাও আমাদের course-index file এ লিখব।
<div>
<table class="w-full table-auto">
<tr>
<th class="border px-4 py-2 text-left">Id </th>
<th class="border px-4 py-2 text-left">Name </th>
<th class="border px-4 py-2 text-left">Description </th>
<th class="border px-4 py-2 text-left">Price</th>
<th class="border px-4 py-2">Created at</th>
<th class="border px-4 py-2">Action</th>
</tr>
@foreach ($courses as $course)
<tr>
<td class="border px-4 py-2">{{ $course->id }}</td>
<td class="border px-4 py-2">{{ $course->name }}</td>
<td class="border px-4 py-2">{{ $course->description }}</td>
<td class="border px-4 py-2">${{ $course->price }}</td>
<td class="border px-4 py-2 text-center">{{ date('F,j,Y',strtotime($course->created_at)) }}</td>
<td class="border px-4 py-2 text-center">
<div class="flex items-center justify-center">
<a href="{{ route('course.edit',$course->id) }}">
@include('components.icons.edit')
</a>
<a class="px-2" href="{{ route('course.show',$course->id) }}">
@include('components.icons.eye')
</a>
<form onsubmit="return confirm('Are you sure?');"
wire:submit.prevent="courseDelete({{ $course->id }})">
<button type="submit">
@include('components.icons.trash')
</button>
</form>
</div>
</td>
</tr>
@endforeach
</table>
</div>
ব্যাস আমাদের টাস্ক complete এটা যেহেতু আমাদের Task class ছিলো তাই সবার code style এক হবে না ।হয়তো কম বেশি এদিক সেদিক হবে তাই মাথা ঠান্ডা করে কাজ করলে আশা করি কোন সমস্যা হবে না । আর সমস্যা হলে তো আমাদের discord group আছেই।
discord link: https://discord.gg/9qWUUbQ3
facebook group :https://web.facebook.com/groups/1661735757554627/
Happy Learning
Rakibul Islam