feat: add profile image support and upload functionality to biker profiles
This commit is contained in:
@@ -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,8 +864,18 @@ 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">
|
||||||
<span className="text-3xl font-bold text-blue-600">{biker.kyc.fullName.charAt(0)}</span>
|
{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>
|
||||||
|
</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>
|
||||||
<div className="flex-1">
|
<div className="flex-1">
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
|
|||||||
@@ -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">
|
||||||
<div className="w-10 h-10 rounded-full bg-blue-100 flex items-center justify-center">
|
{biker.profileImage ? (
|
||||||
<span className="text-sm font-bold text-blue-600">{biker.name.charAt(0)}</span>
|
<img src={biker.profileImage} alt={biker.name} className="w-10 h-10 rounded-full object-cover" />
|
||||||
</div>
|
) : (
|
||||||
|
<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>
|
||||||
|
</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">
|
||||||
<div className="w-12 h-12 rounded-full bg-blue-100 flex items-center justify-center">
|
{biker.profileImage ? (
|
||||||
<span className="text-lg font-bold text-blue-600">{biker.name.charAt(0)}</span>
|
<img src={biker.profileImage} alt={biker.name} className="w-12 h-12 rounded-full object-cover" />
|
||||||
</div>
|
) : (
|
||||||
|
<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>
|
||||||
|
</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">
|
||||||
<div className="w-12 h-12 rounded-full bg-blue-100 flex items-center justify-center">
|
{biker.profileImage ? (
|
||||||
<span className="text-lg font-bold text-blue-600">{biker.name.charAt(0)}</span>
|
<img src={biker.profileImage} alt={biker.name} className="w-12 h-12 rounded-full object-cover" />
|
||||||
</div>
|
) : (
|
||||||
|
<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>
|
||||||
|
</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">
|
||||||
<div className="w-20 h-20 rounded-full bg-blue-100 flex items-center justify-center">
|
{selectedBiker.profileImage ? (
|
||||||
<span className="text-3xl font-bold text-blue-600">{selectedBiker.name.charAt(0)}</span>
|
<img src={selectedBiker.profileImage} alt={selectedBiker.name} className="w-20 h-20 rounded-full object-cover" />
|
||||||
</div>
|
) : (
|
||||||
|
<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>
|
||||||
|
</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>
|
||||||
|
|||||||
Reference in New Issue
Block a user