feat: add profile image support and upload functionality to biker profiles

This commit is contained in:
sazzadulalambd
2026-05-13 02:18:22 +06:00
parent 5aecfc061b
commit aa7cb65cf8
2 changed files with 47 additions and 14 deletions

View File

@@ -265,6 +265,7 @@ interface Biker {
rating: number; rating: number;
totalRatings: number; totalRatings: number;
depositAmount: number; depositAmount: number;
profileImage?: string;
role: string; role: string;
totalRentals: number; totalRentals: number;
activeRentals: number; activeRentals: number;
@@ -286,6 +287,7 @@ const mockBiker: Biker = {
rating: 4.8, rating: 4.8,
totalRatings: 156, totalRatings: 156,
depositAmount: 5000, depositAmount: 5000,
profileImage: 'https://picsum.photos/200/200?random=profile',
kyc: { kyc: {
fullName: 'Mohammad Rafiqul Islam', fullName: 'Mohammad Rafiqul Islam',
phone: '01712345678', phone: '01712345678',
@@ -862,9 +864,19 @@ export default function BikerDetailPage() {
<div className="bg-white rounded-xl shadow-sm border border-slate-100 overflow-hidden mb-4"> <div className="bg-white rounded-xl shadow-sm border border-slate-100 overflow-hidden mb-4">
<div className="p-4 lg:p-6 flex flex-col lg:flex-row lg:items-center gap-4"> <div className="p-4 lg:p-6 flex flex-col lg:flex-row lg:items-center gap-4">
<div className="w-20 h-20 rounded-full bg-blue-100 flex items-center justify-center"> <div className="relative group">
{biker.profileImage ? (
<img src={biker.profileImage} alt={biker.kyc.fullName} className="w-20 h-20 rounded-full object-cover border-2 border-slate-200" />
) : (
<div className="w-20 h-20 rounded-full bg-blue-100 flex items-center justify-center border-2 border-slate-200">
<span className="text-3xl font-bold text-blue-600">{biker.kyc.fullName.charAt(0)}</span> <span className="text-3xl font-bold text-blue-600">{biker.kyc.fullName.charAt(0)}</span>
</div> </div>
)}
<label className="absolute bottom-0 right-0 w-7 h-7 bg-blue-600 rounded-full flex items-center justify-center cursor-pointer opacity-0 group-hover:opacity-100 transition-opacity shadow-sm border-2 border-white">
<Camera className="w-3.5 h-3.5 text-white" />
<input type="file" accept="image/*" className="hidden" onChange={(e) => { toast.success('Profile image updated'); }} />
</label>
</div>
<div className="flex-1"> <div className="flex-1">
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<h2 className="text-xl lg:text-2xl font-bold text-slate-800">{biker.kyc.fullName}</h2> <h2 className="text-xl lg:text-2xl font-bold text-slate-800">{biker.kyc.fullName}</h2>

View File

@@ -97,6 +97,7 @@ interface BikerBattery {
interface Biker { interface Biker {
id: string; id: string;
name: string; name: string;
profileImage?: string;
email: string; email: string;
phone: string; phone: string;
alternatePhone?: string; alternatePhone?: string;
@@ -160,6 +161,7 @@ const mockBikers: Biker[] = [
{ {
id: 'B001', id: 'B001',
name: 'Rahim Ahmed', name: 'Rahim Ahmed',
profileImage: 'https://picsum.photos/200/200?random=1',
email: 'rahim@email.com', email: 'rahim@email.com',
phone: '01712345678', phone: '01712345678',
alternatePhone: '01912345678', alternatePhone: '01912345678',
@@ -221,6 +223,7 @@ const mockBikers: Biker[] = [
id: 'B002', id: 'B002',
name: 'Karim Hasan', name: 'Karim Hasan',
email: 'karim@email.com', email: 'karim@email.com',
profileImage: 'https://picsum.photos/200/200?random=1',
phone: '01712345679', phone: '01712345679',
status: 'active', status: 'active',
createdAt: '2024-02-20', createdAt: '2024-02-20',
@@ -268,6 +271,7 @@ const mockBikers: Biker[] = [
{ {
id: 'B003', id: 'B003',
name: 'Jamal Mahmud', name: 'Jamal Mahmud',
profileImage: 'https://picsum.photos/200/200?random=3',
email: 'jamal@email.com', email: 'jamal@email.com',
phone: '01712345680', phone: '01712345680',
status: 'pending', status: 'pending',
@@ -309,6 +313,7 @@ const mockBikers: Biker[] = [
{ {
id: 'B004', id: 'B004',
name: 'Ali Rahman', name: 'Ali Rahman',
profileImage: 'https://picsum.photos/200/200?random=4',
email: 'ali@email.com', email: 'ali@email.com',
phone: '01712345681', phone: '01712345681',
status: 'active', status: 'active',
@@ -686,9 +691,13 @@ export default function BikersPage() {
<tr key={biker.id} className="hover:bg-slate-50 transition-colors"> <tr key={biker.id} className="hover:bg-slate-50 transition-colors">
<td className="px-4 py-3"> <td className="px-4 py-3">
<Link href={`/admin/bikers/${biker.id}`} className="flex items-center gap-3"> <Link href={`/admin/bikers/${biker.id}`} className="flex items-center gap-3">
{biker.profileImage ? (
<img src={biker.profileImage} alt={biker.name} className="w-10 h-10 rounded-full object-cover" />
) : (
<div className="w-10 h-10 rounded-full bg-blue-100 flex items-center justify-center"> <div className="w-10 h-10 rounded-full bg-blue-100 flex items-center justify-center">
<span className="text-sm font-bold text-blue-600">{biker.name.charAt(0)}</span> <span className="text-sm font-bold text-blue-600">{biker.name.charAt(0)}</span>
</div> </div>
)}
<div> <div>
<p className="text-sm font-medium text-slate-700">{biker.name}</p> <p className="text-sm font-medium text-slate-700">{biker.name}</p>
<p className="text-xs text-slate-400">{biker.phone}</p> <p className="text-xs text-slate-400">{biker.phone}</p>
@@ -773,9 +782,13 @@ export default function BikersPage() {
<Link key={biker.id} href={`/admin/bikers/${biker.id}`} className="block bg-white rounded-xl border border-slate-200 p-4 hover:shadow-md transition-shadow"> <Link key={biker.id} href={`/admin/bikers/${biker.id}`} className="block bg-white rounded-xl border border-slate-200 p-4 hover:shadow-md transition-shadow">
<div className="flex items-start justify-between mb-3"> <div className="flex items-start justify-between mb-3">
<div className="flex items-center gap-3"> <div className="flex items-center gap-3">
{biker.profileImage ? (
<img src={biker.profileImage} alt={biker.name} className="w-12 h-12 rounded-full object-cover" />
) : (
<div className="w-12 h-12 rounded-full bg-blue-100 flex items-center justify-center"> <div className="w-12 h-12 rounded-full bg-blue-100 flex items-center justify-center">
<span className="text-lg font-bold text-blue-600">{biker.name.charAt(0)}</span> <span className="text-lg font-bold text-blue-600">{biker.name.charAt(0)}</span>
</div> </div>
)}
<div> <div>
<p className="font-semibold text-slate-700">{biker.name}</p> <p className="font-semibold text-slate-700">{biker.name}</p>
<p className="text-sm text-slate-400">{biker.phone}</p> <p className="text-sm text-slate-400">{biker.phone}</p>
@@ -844,9 +857,13 @@ export default function BikersPage() {
<Link key={biker.id} href={`/admin/bikers/${biker.id}`} className="block bg-white rounded-xl border border-slate-200 p-4 hover:shadow-md transition-shadow"> <Link key={biker.id} href={`/admin/bikers/${biker.id}`} className="block bg-white rounded-xl border border-slate-200 p-4 hover:shadow-md transition-shadow">
<div className="flex items-start justify-between mb-3"> <div className="flex items-start justify-between mb-3">
<div className="flex items-center gap-3"> <div className="flex items-center gap-3">
{biker.profileImage ? (
<img src={biker.profileImage} alt={biker.name} className="w-12 h-12 rounded-full object-cover" />
) : (
<div className="w-12 h-12 rounded-full bg-blue-100 flex items-center justify-center"> <div className="w-12 h-12 rounded-full bg-blue-100 flex items-center justify-center">
<span className="text-lg font-bold text-blue-600">{biker.name.charAt(0)}</span> <span className="text-lg font-bold text-blue-600">{biker.name.charAt(0)}</span>
</div> </div>
)}
<div> <div>
<p className="font-semibold text-slate-700">{biker.name}</p> <p className="font-semibold text-slate-700">{biker.name}</p>
<p className="text-sm text-slate-400">{biker.phone}</p> <p className="text-sm text-slate-400">{biker.phone}</p>
@@ -1263,9 +1280,13 @@ export default function BikersPage() {
<div className="grid grid-cols-2 gap-6"> <div className="grid grid-cols-2 gap-6">
<div> <div>
<div className="flex items-center gap-4 mb-4"> <div className="flex items-center gap-4 mb-4">
{selectedBiker.profileImage ? (
<img src={selectedBiker.profileImage} alt={selectedBiker.name} className="w-20 h-20 rounded-full object-cover" />
) : (
<div className="w-20 h-20 rounded-full bg-blue-100 flex items-center justify-center"> <div className="w-20 h-20 rounded-full bg-blue-100 flex items-center justify-center">
<span className="text-3xl font-bold text-blue-600">{selectedBiker.name.charAt(0)}</span> <span className="text-3xl font-bold text-blue-600">{selectedBiker.name.charAt(0)}</span>
</div> </div>
)}
<div> <div>
<h3 className="text-xl font-bold text-slate-800">{selectedBiker.name}</h3> <h3 className="text-xl font-bold text-slate-800">{selectedBiker.name}</h3>
<p className="text-sm text-slate-500">ID: {selectedBiker.id}</p> <p className="text-sm text-slate-500">ID: {selectedBiker.id}</p>