+
{user.name ? user.name.charAt(0).toUpperCase() : "U"}
)}
@@ -68,7 +67,7 @@ export default async function ProfilePage() {
Edit Profile
@@ -84,7 +83,7 @@ export default async function ProfilePage() {
My Equipment Listings
Add New Equipment
@@ -95,7 +94,7 @@ export default async function ProfilePage() {
You haven't listed any equipment yet.
List Your First Equipment
@@ -188,7 +187,7 @@ export default async function ProfilePage() {
You haven't rented any equipment yet.
Browse Equipment
@@ -228,11 +227,11 @@ export default async function ProfilePage() {
diff --git a/src/app/routes/rentals/[id]/page.tsx b/src/app/routes/rentals/[id]/page.tsx
index 16e099c..bea2dd3 100644
--- a/src/app/routes/rentals/[id]/page.tsx
+++ b/src/app/routes/rentals/[id]/page.tsx
@@ -6,19 +6,18 @@ import { formatCurrency, formatDateRange } from "@/lib/utils/format";
import { RentalActions } from "@/components/rentals/rental-actions";
interface RentalDetailPageProps {
- params: {
- id: string;
- };
+ params: Promise<{ id: string }>;
}
export default async function RentalDetailPage({ params }: RentalDetailPageProps) {
// Ensure user is authenticated
const user = await requireAuth();
+ const { id } = await params;
// Fetch the rental
const rental = await db.rental.findUnique({
where: {
- id: params.id,
+ id,
},
include: {
equipment: {
@@ -56,7 +55,7 @@ export default async function RentalDetailPage({ params }: RentalDetailPageProps
return (
-
+
{/* Review Section */}
- {rental.status === "Completed" && !rental.review && !isOwner && (
+ {rental.status === "COMPLETED" && !rental.review && !isOwner && (
Leave a Review
Write a Review
@@ -204,7 +203,7 @@ export default async function RentalDetailPage({ params }: RentalDetailPageProps
key={star}
xmlns="http://www.w3.org/2000/svg"
className={`h-5 w-5 ${
- star <= rental.review.rating
+ star <= (rental.review?.rating ?? 0)
? "text-yellow-400"
: "text-gray-300"
}`}
diff --git a/src/app/routes/rentals/[id]/payment/page.tsx b/src/app/routes/rentals/[id]/payment/page.tsx
index 0854641..2c4cc63 100644
--- a/src/app/routes/rentals/[id]/payment/page.tsx
+++ b/src/app/routes/rentals/[id]/payment/page.tsx
@@ -2,116 +2,58 @@ import { redirect } from "next/navigation";
import { PaymentFormWrapper } from "@/components/payments/payment-form";
import { db } from "@/lib/db";
import { getCurrentUser } from "@/lib/auth/session";
-import { formatAmountFromStripe } from "@/lib/stripe";
-interface PaymentPageProps {
- params: {
- id: string;
- };
-}
+interface PaymentPageProps { params: Promise<{ id: string }> }
export default async function PaymentPage({ params }: PaymentPageProps) {
- const currentUser = await getCurrentUser();
-
- if (!currentUser) {
- redirect("/auth/login?callbackUrl=/rentals");
- }
+ const user = await getCurrentUser();
+ if (!user) redirect("/auth/login?callbackUrl=/routes/rentals");
+ const { id } = await params;
const rental = await db.rental.findUnique({
- where: {
- id: params.id,
- renterId: currentUser.id,
- },
- include: {
- equipment: {
- include: {
- owner: true,
- },
- },
- payment: true,
- },
+ where: { id },
+ include: { equipment: { select: { title: true, owner: { select: { name: true } } } }, payment: true },
});
-
- if (!rental) {
- redirect("/rentals?error=rental-not-found");
- }
-
- if (rental.status !== "Pending") {
- redirect(`/rentals?error=invalid-status&status=${rental.status}`);
+ if (!rental || rental.renterId !== user.id) redirect("/routes/rentals");
+ if (rental.status !== 'PENDING' || Date.now() - rental.createdAt.getTime() > 30 * 60 * 1000) {
+ redirect("/routes/rentals?error=expired");
}
- // Calculate total amount including security deposit
- const totalAmount = rental.totalPrice;
- const securityDeposit = rental.securityDeposit || 0;
- const totalWithDeposit = totalAmount + securityDeposit;
-
- if (!rental.payment) {
- // Create a payment record if it doesn't exist
- const payment = await db.payment.create({
- data: {
- amount: totalAmount, // Just the rental amount initially
- currency: "USD",
- status: "Pending",
- userId: currentUser.id,
- rentalId: rental.id,
- },
- });
-
- // Refresh the page to get the payment
- redirect(`/routes/rentals/${rental.id}/payment`);
- }
+ const payment = await db.payment.upsert({
+ where: { rentalId: rental.id },
+ update: {},
+ create: {
+ amount: Math.round((rental.totalPrice + (rental.securityDeposit ?? 0)) * 100) / 100,
+ currency: 'USD',
+ status: 'PENDING',
+ userId: user.id,
+ rentalId: rental.id,
+ },
+ });
return (
Complete Your Payment
-
-
-
- Rental Details
-
- Equipment: {rental.equipment.title}
- Owner: {rental.equipment.owner.name}
- Start Date: {new Date(rental.startDate).toLocaleDateString()}
- End Date: {new Date(rental.endDate).toLocaleDateString()}
- Rental Price: ${rental.totalPrice.toFixed(2)}
- {rental.securityDeposit && rental.securityDeposit > 0 && (
- <>
- Security Deposit: ${rental.securityDeposit.toFixed(2)}
- Total Amount: ${totalWithDeposit.toFixed(2)}
- >
- )}
-
-
-
-
- Payment Information
-
- Your payment is processed securely through Stripe. We do not store your card details.
-
- {rental.securityDeposit && rental.securityDeposit > 0 && (
-
- About Your Security Deposit
- The security deposit of ${rental.securityDeposit.toFixed(2)} will be held and returned to you after the rental period, assuming the equipment is returned in the same condition.
-
- )}
-
- You will only be charged once the owner approves your rental request.
-
-
-
-
-
- redirect("/rentals")}
- />
+
+ Rental Details
+ Equipment: {rental.equipment.title}
+ Owner: {rental.equipment.owner.name}
+ Start: {rental.startDate.toLocaleDateString()}
+ End: {rental.endDate.toLocaleDateString()}
+ Rental amount: ${rental.totalPrice.toFixed(2)}
+ Refundable deposit: ${(rental.securityDeposit ?? 0).toFixed(2)}
+ Pay today: ${(rental.totalPrice + (rental.securityDeposit ?? 0)).toFixed(2)}
+ Payment is charged when you complete checkout. The owner can then start your rental.
+
);
-}
\ No newline at end of file
+}
diff --git a/src/app/routes/rentals/[id]/review/page.tsx b/src/app/routes/rentals/[id]/review/page.tsx
index d5637d4..88bf5a1 100644
--- a/src/app/routes/rentals/[id]/review/page.tsx
+++ b/src/app/routes/rentals/[id]/review/page.tsx
@@ -5,9 +5,7 @@ import { db } from "@/lib/db";
import { ReviewForm } from "@/components/reviews/review-form";
interface RentalReviewPageProps {
- params: {
- id: string;
- };
+ params: Promise<{ id: string }>;
}
export default async function RentalReviewPage({ params }: RentalReviewPageProps) {
@@ -20,7 +18,7 @@ export default async function RentalReviewPage({ params }: RentalReviewPageProps
// Fetch the rental with equipment details
const rental = await db.rental.findUnique({
where: {
- id: params.id,
+ id: (await params).id,
renterId: user.id, // Ensure the user is the renter
},
include: {
@@ -46,20 +44,20 @@ export default async function RentalReviewPage({ params }: RentalReviewPageProps
}
// Check if the rental is completed
- if (rental.status !== "Completed") {
- redirect(`/routes/rentals/${params.id}`);
+ if (rental.status !== "COMPLETED") {
+ redirect(`/routes/rentals/${(await params).id}`);
}
// Check if the user has already reviewed this rental
const existingReview = await db.review.findFirst({
where: {
- rentalId: params.id,
+ rentalId: (await params).id,
authorId: user.id,
},
});
if (existingReview) {
- redirect(`/routes/rentals/${params.id}`);
+ redirect(`/routes/rentals/${(await params).id}`);
}
// Parse equipment images
@@ -75,7 +73,7 @@ export default async function RentalReviewPage({ params }: RentalReviewPageProps
|