feat: broker profile

- add morph to relationship
- add profile markup
- modify page-heading.blade.php to accept center and end sections
This commit is contained in:
kusowl 2026-01-13 18:06:27 +05:30
parent cdcb75cb58
commit 1275a74506
12 changed files with 230 additions and 25 deletions

View File

@ -0,0 +1,45 @@
<?php
namespace App\Http\Controllers\Broker;
use App\Http\Controllers\Controller;
use App\Models\User;
use Illuminate\Http\Request;
class BrokerProfileController extends Controller
{
/**
* Display the specified resource.
*/
public function show(User $profile)
{
return view('dashboards.broker.profile.show')
->with('name', $profile->name)
->with('joinDate', $profile->created_at->format('F Y'))
->with('email', $profile->email);
}
/**
* Show the form for editing the specified resource.
*/
public function edit(string $id)
{
//
}
/**
* Update the specified resource in storage.
*/
public function update(Request $request, string $id)
{
//
}
/**
* Remove the specified resource from storage.
*/
public function destroy(string $id)
{
//
}
}

View File

@ -52,14 +52,6 @@ public function store(StoreBrokerDeal $request, FileService $fileService)
return to_route('broker.dashboard')->with('success', 'Deal has been created.'); return to_route('broker.dashboard')->with('success', 'Deal has been created.');
} }
/**
* Display the specified resource.
*/
public function show(string $id)
{
//
}
/** /**
* Show the form for editing the specified resource. * Show the form for editing the specified resource.
*/ */

22
app/Models/Broker.php Normal file
View File

@ -0,0 +1,22 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\MorphOne;
class Broker extends Model
{
protected function casts(): array
{
return [
'verified' => 'boolean',
'active' => 'boolean',
];
}
public function user(): MorphOne
{
return $this->morphOne(User::class, 'type');
}
}

View File

@ -5,7 +5,9 @@
// use Illuminate\Contracts\Auth\MustVerifyEmail; // use Illuminate\Contracts\Auth\MustVerifyEmail;
use App\Enums\UserTypes; use App\Enums\UserTypes;
use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\MorphTo;
use Illuminate\Foundation\Auth\User as Authenticatable; use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable; use Illuminate\Notifications\Notifiable;
@ -59,4 +61,12 @@ public function deals(): HasMany
{ {
return $this->hasMany(Deal::class); return $this->hasMany(Deal::class);
} }
/**
* Returns model of User's type
*/
public function type(): MorphTo
{
return $this->morphTo();
}
} }

View File

@ -0,0 +1,32 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('brokers', function (Blueprint $table) {
$table->id();
$table->text('bio');
$table->string('location');
$table->string('phone')->nullable();
$table->boolean('verified')->default(false);
$table->boolean('active')->default(true);
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('brokers');
}
};

View File

@ -0,0 +1,28 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('users', function (Blueprint $table) {
$table->nullableMorphs('type');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('users', function (Blueprint $table) {
$table->dropMorphs('type');
});
}
};

View File

@ -10,7 +10,7 @@
<!-- desktop menu --> <!-- desktop menu -->
<div class="nav-ui buttons space-x-4 font-medium hidden md:flex "> <div class="nav-ui buttons space-x-4 font-medium hidden md:flex ">
<a href="" class="ui-btn flex border space-x-3 border-gray-200 items-center"> <a href="{{route('broker.profile.show', auth()->user()->id)}}" class="ui-btn flex border space-x-3 border-gray-200 items-center">
<x-heroicon-o-user class="w-6"/> <x-heroicon-o-user class="w-6"/>
<p>Profile</p> <p>Profile</p>
</a> </a>

View File

@ -1,17 +1,29 @@
@props(['title' => '', 'description' => '', 'backLink' => '']) @props(['title' => '', 'description' => '', 'backLink' => ''])
<section class="flex space-x-6 items-center wrapper py-6 shadow"> <section class="flex space-x-6 items-center justify-between wrapper py-6 shadow">
<div class="flex space-x-6 items-center">
@if($backLink !== '') @if($backLink !== '')
<div class=""> <div class="">
<a href="{{$backLink}}"> <a href="{{$backLink}}">
<x-heroicon-o-arrow-left class="w-4"/> <x-heroicon-o-arrow-left class="w-4"/>
</a> </a>
</div> </div>
@endif
<div class="">
<h1 class="text-xl font-bold">{{$title}}</h1>
@if($description !== '')
<p class="text-sm text-accent-600">{{$description}}</p>
@endif @endif
<div class="">
<h1 class="text-xl font-bold">{{$title}}</h1>
@if($description !== '')
<p class="text-sm text-accent-600">{{$description}}</p>
@endif
</div>
</div>
<div class="">
@isset($center)
{{ $center }}
@endisset
</div>
<div class="">
@isset($end)
{{ $end }}
@endisset
</div> </div>
</section> </section>

View File

@ -7,6 +7,6 @@
$variantClass = $variants[$variant] ?? ''; $variantClass = $variants[$variant] ?? '';
@endphp @endphp
<button {{$attributes->merge(['class' => "px-6 py-1 rounded-md font-medium hover:opacity-80 $variantClass"])}}> <button {{$attributes->merge(['class' => "px-2 py-1 text-xs rounded-md font-medium hover:opacity-80 $variantClass"])}}>
{{$slot}} {{$slot}}
</button> </button>

View File

@ -8,7 +8,7 @@
$variantClass = $variants[$variant] ?? ''; $variantClass = $variants[$variant] ?? '';
@endphp @endphp
@if($link !== '') @if($link !== '')
<a {{$attributes->merge(['class' => "px-4 py-2 rounded-lg font-medium hover:opacity-80 $variantClass", 'href' => $link])}}> <a {{$attributes->merge(['class' => "block px-4 py-2 rounded-lg font-medium hover:opacity-80 $variantClass", 'href' => $link])}}>
<div class="flex justify-center items-center space-x-2"> <div class="flex justify-center items-center space-x-2">
@if($icon !=='') @if($icon !=='')
@svg("heroicon-o-$icon", 'w-5 h-5') @svg("heroicon-o-$icon", 'w-5 h-5')

View File

@ -0,0 +1,61 @@
<x-layout title="Profile">
<x-dashboard.page-heading
title="Broker Profile"
description="Public profile information"
:back-link="route('broker.dashboard')"
>
<x-slot:end>
<x-ui.button :link="route('broker.profile.edit', auth()->user()->id)" class="border border-accent-600/40">
Edit Profile
</x-ui.button>
</x-slot:end>
</x-dashboard.page-heading>
<div class="flex items-center justify-center">
<div class="flex items-center justify-center mt-8 max-w-10/12">
<x-dashboard.card>
<div class="grid grid-cols-8 gap-6">
<div class="col-span-8 place-self-start md:col-span-1 flex items-center justify-center w-full">
<div class="w-25 h-25 rounded-xl bg-linear-150 from-[#305afc] to-[#941dfb] text-5xl text-white flex justify-center items-center">UR
</div>
</div>
<div class="col-span-8 md:col-span-7 flex flex-col space-y-6">
<div class="">
<p class="text-3xl font-bold">{{$name ?? 'Name'}}</p>
<div class="flex space-x-1 mt-2">
<x-ui.button-sm variant="neutral">Verified Broker</x-ui.button-sm>
<x-heroicon-s-star class="ml-2 w-4 fill-amber-300"/>
<p>4.8</p>
</div>
</div>
<div class="">
<p>{{$bio ?? 'Bio is empty'}}</p>
</div>
<div class="grid grid-cols-2 grid-rows-2 gap-3">
<div class="fill-accent-600/70 text-accent-600/70 flex space-x-4 text-sm items-center">
<x-heroicon-o-envelope class="w-4" />
<p>{{$email ?? 'email is empty'}}</p>
</div>
<div class="fill-accent-600/70 text-accent-600/70 flex space-x-4 text-sm items-center">
<x-heroicon-o-phone class="w-4" />
<p>{{$phone ?? 'phone is empty'}}</p>
</div>
<div class="fill-accent-600/70 text-accent-600/70 flex space-x-4 text-sm items-center">
<x-heroicon-o-map class="w-4" />
<p>{{$location ?? 'location is empty'}}</p>
</div>
<div class="fill-accent-600/70 text-accent-600/70 flex space-x-4 text-sm items-center">
<x-heroicon-o-arrow-trending-up class="w-4" />
<p>Joined {{$joinDate ?? 'date is empty'}}</p>
</div>
</div>
</div>
</div>
</x-dashboard.card>
</div>
</div>
</x-layout>

View File

@ -3,6 +3,7 @@
use App\Enums\UserTypes; use App\Enums\UserTypes;
use App\Http\Controllers\AuthenticatedUserController; use App\Http\Controllers\AuthenticatedUserController;
use App\Http\Controllers\Broker\BrokerDashboardController; use App\Http\Controllers\Broker\BrokerDashboardController;
use App\Http\Controllers\Broker\BrokerProfileController;
use App\Http\Controllers\BrokerDealController; use App\Http\Controllers\BrokerDealController;
use App\Http\Controllers\HomeController; use App\Http\Controllers\HomeController;
use App\Http\Controllers\RegisteredUserController; use App\Http\Controllers\RegisteredUserController;
@ -33,6 +34,8 @@
->group(function () { ->group(function () {
Route::get('dashboard', [BrokerDashboardController::class, 'index'])->name('dashboard'); Route::get('dashboard', [BrokerDashboardController::class, 'index'])->name('dashboard');
Route::resource('deals', BrokerDealController::class); Route::resource('deals', BrokerDealController::class)->except('show');
Route::resource('profile', BrokerProfileController::class)->except('index', 'store', 'create');
}); });
}); });