205 lines
7.1 KiB
TypeScript
205 lines
7.1 KiB
TypeScript
import { Avatar, AvatarFallback, AvatarImage } from "./ui/avatar";
|
|
import { Button } from "./ui/button";
|
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle, } from "./ui/card";
|
|
import { Input } from "./ui/input";
|
|
import { Label } from "./ui/label";
|
|
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue,} from "./ui/select";
|
|
import { Separator } from "./ui/separator";
|
|
import { Textarea } from "./ui/textarea";
|
|
import React, { useState, useEffect } from 'react';
|
|
import UpdateAvatar from './UpdateAvatar';
|
|
|
|
interface SessionData {
|
|
[key: string]: any;
|
|
}
|
|
|
|
interface UserData {
|
|
success: boolean;
|
|
session_data: SessionData;
|
|
user_avatar: string;
|
|
}
|
|
|
|
|
|
export default function ProfilePage() {
|
|
const [userData, setUserData] = useState<UserData | null>(null);
|
|
const [invoiceList, setInvoiceList] = useState<any[]>([]);
|
|
const [error, setError] = useState<string | null>(null);
|
|
|
|
useEffect(() => {
|
|
const fetchSessionData = async () => {
|
|
try {
|
|
const response = await fetch(
|
|
'http://localhost:2058/host-api/v1/users/get-profile-data/',
|
|
{
|
|
credentials: 'include', // Crucial for cookies
|
|
headers: { 'Accept': 'application/json' }
|
|
}
|
|
);
|
|
|
|
const data = await response.json();
|
|
if (!response.ok || !data.success) {
|
|
throw new Error(data.error || 'Session fetch failed');
|
|
}
|
|
setUserData(data);
|
|
return data.session_data;
|
|
} catch (error) {
|
|
console.error('Fetch error:', error);
|
|
throw error;
|
|
}
|
|
};
|
|
const getInvoiceListData = async () => {
|
|
try {
|
|
const response = await fetch('http://localhost:2058/host-api/v1/invoice/invoice-info/', {
|
|
method: 'GET',
|
|
credentials: 'include', // Crucial for cookies
|
|
headers: { 'Accept': 'application/json' }
|
|
});
|
|
|
|
if (!response.ok) {
|
|
throw new Error(`HTTP error! Status: ${response.status}`);
|
|
}
|
|
|
|
const data = await response.json();
|
|
|
|
if (!data.success) {
|
|
throw new Error(data.message || 'Session fetch failed');
|
|
}
|
|
|
|
setInvoiceList(data.data); // Fix: Use `data.data` instead of `data`
|
|
return data.data; // Fix: `session_data` does not exist in response
|
|
} catch (error) {
|
|
console.error('Fetch error:', error);
|
|
throw error;
|
|
}
|
|
};
|
|
|
|
|
|
|
|
fetchSessionData();
|
|
getInvoiceListData();
|
|
}, []);
|
|
|
|
if (error) {
|
|
return <div>Error: {error}</div>;
|
|
}
|
|
|
|
if (!userData) {
|
|
return <div>Loading profile data...</div>;
|
|
}
|
|
return (
|
|
<div className="space-y-6 container mx-auto">
|
|
<Separator />
|
|
<div className="flex flex-col space-y-8 lg:flex-row lg:space-x-12 lg:space-y-0">
|
|
<div className="flex-1 lg:max-w-2xl">
|
|
<Card>
|
|
<CardHeader>
|
|
<CardTitle>Personal Information</CardTitle>
|
|
<CardDescription>
|
|
Update your personal information and avatar.
|
|
</CardDescription>
|
|
</CardHeader>
|
|
<CardContent className="space-y-6">
|
|
<div className="flex items-center space-x-4">
|
|
<Avatar className="h-16 w-16">
|
|
<AvatarImage src={userData.session_data?.user_avatar} />
|
|
<AvatarFallback>JP</AvatarFallback>
|
|
</Avatar>
|
|
<UpdateAvatar />
|
|
|
|
</div>
|
|
|
|
<div className="grid grid-cols-1 gap-4 sm:grid-cols-2">
|
|
<div className="space-y-2">
|
|
<Label htmlFor="firstName">Full Name</Label>
|
|
<Input id="firstName" defaultValue={userData.session_data?.user_name || 'Jhon'} />
|
|
</div>
|
|
<div className="space-y-2">
|
|
<Label htmlFor="phone">Phone</Label>
|
|
<Input id="phone" defaultValue={userData.session_data?.user_vatar || ''} />
|
|
</div>
|
|
</div>
|
|
|
|
<div className="space-y-2">
|
|
<Label htmlFor="email">Email</Label>
|
|
<Input id="email" type="email" defaultValue={userData.session_data?.user_email || ''} />
|
|
</div>
|
|
|
|
</CardContent>
|
|
</Card>
|
|
<Card className="mt-6">
|
|
<CardHeader>
|
|
<CardTitle>Billing Information</CardTitle>
|
|
<CardDescription>
|
|
View your billing history.
|
|
</CardDescription>
|
|
<table className="w-full">
|
|
<thead>
|
|
<tr>
|
|
<th className="text-left">Invoice ID</th>
|
|
<th className="text-left">Date</th>
|
|
<th className="text-left">Description</th>
|
|
<th className="text-right">Amount</th>
|
|
<th className="text-center">Action</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{
|
|
invoiceList.map((invoice) => (
|
|
<tr key={invoice.id}>
|
|
<td>{invoice.invoice_id}</td>
|
|
<td>{invoice.date}</td>
|
|
<td>{invoice.description}</td>
|
|
<td className="text-right">{invoice.amount}</td>
|
|
<td className="text-center"><a href="">Print</a></td>
|
|
</tr>
|
|
))
|
|
}
|
|
</tbody>
|
|
</table>
|
|
</CardHeader>
|
|
</Card>
|
|
</div>
|
|
|
|
<div className="flex-1 space-y-6 lg:max-w-md">
|
|
<Card>
|
|
<CardHeader>
|
|
<CardTitle>Security</CardTitle>
|
|
<CardDescription>
|
|
Update your password and security settings.
|
|
</CardDescription>
|
|
</CardHeader>
|
|
<CardContent className="space-y-4">
|
|
<div className="space-y-2">
|
|
<Label htmlFor="currentPassword">Current password</Label>
|
|
<Input id="currentPassword" type="password" />
|
|
</div>
|
|
<div className="space-y-2">
|
|
<Label htmlFor="newPassword">New password</Label>
|
|
<Input id="newPassword" type="password" />
|
|
</div>
|
|
<div className="space-y-2">
|
|
<Label htmlFor="confirmPassword">Confirm password</Label>
|
|
<Input id="confirmPassword" type="password" />
|
|
</div>
|
|
<Button className="mt-4">Update password</Button>
|
|
</CardContent>
|
|
</Card>
|
|
<Card className="mt-6">
|
|
<CardHeader>
|
|
<CardTitle>Danger Zone</CardTitle>
|
|
<CardDescription>
|
|
These actions are irreversible. Proceed with caution.
|
|
</CardDescription>
|
|
</CardHeader>
|
|
<CardContent>
|
|
<div className="flex flex-col space-y-4">
|
|
<Button className="bg-red-500 hover:bg-red-600">Delete account</Button>
|
|
<Button variant="outline">Export data</Button>
|
|
</div>
|
|
</CardContent>
|
|
</Card>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
} |