From 546c8817017d33b8f094a3299b9f64e3cf17ef15 Mon Sep 17 00:00:00 2001 From: jackiettran <41605212+jackiettran@users.noreply.github.com> Date: Tue, 30 Dec 2025 00:20:15 -0500 Subject: [PATCH] rental price calculation bug, sticky pricing cards on mobile, bigger font app wide, removed delivery options from frontened, searching by location with zipcode works when there's multiple zipcodes in the area, --- backend/utils/rentalDurationCalculator.js | 4 +- frontend/src/App.css | 57 ++++++ frontend/src/components/DeliveryOptions.tsx | 60 ------ .../src/components/LocationPromptModal.tsx | 33 +++- frontend/src/index.css | 4 + frontend/src/mocks/handlers.ts | 1 - frontend/src/pages/CreateItem.tsx | 11 -- frontend/src/pages/EditItem.tsx | 13 -- frontend/src/pages/ItemDetail.tsx | 71 ++++++- frontend/src/pages/ItemList.tsx | 33 ++-- frontend/src/pages/RentItem.tsx | 182 +++++++++--------- frontend/src/types/index.ts | 7 - 12 files changed, 254 insertions(+), 222 deletions(-) delete mode 100644 frontend/src/components/DeliveryOptions.tsx diff --git a/backend/utils/rentalDurationCalculator.js b/backend/utils/rentalDurationCalculator.js index 5136a0e..67113bf 100644 --- a/backend/utils/rentalDurationCalculator.js +++ b/backend/utils/rentalDurationCalculator.js @@ -33,8 +33,8 @@ class RentalDurationCalculator { // Calculate base amount based on duration (tiered pricing) let totalAmount; - if (item.pricePerHour && diffHours <= 24) { - // Use hourly rate for rentals <= 24 hours + if (item.pricePerHour && diffHours < 24) { + // Use hourly rate for rentals under 24 hours totalAmount = diffHours * Number(item.pricePerHour); } else if (diffDays <= 7 && item.pricePerDay) { // Use daily rate for rentals <= 7 days diff --git a/frontend/src/App.css b/frontend/src/App.css index 0703e76..b6c94d7 100644 --- a/frontend/src/App.css +++ b/frontend/src/App.css @@ -54,4 +54,61 @@ main { .navbar .container-fluid { justify-content: space-between; } +} + +/* Mobile Sticky Bottom Bar for Item Detail */ +.mobile-sticky-bottom-bar { + position: fixed; + bottom: 0; + left: 0; + right: 0; + background: white; + padding: 12px 16px; + box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.1); + z-index: 1000; + border-top: 1px solid #e0e0e0; +} + +/* Mobile-specific styles */ +@media (max-width: 767.98px) { + /* Make sticky card non-sticky on mobile */ + .sticky-pricing-card { + position: static !important; + margin-bottom: 80px; + } +} + +/* Pricing card input sizing - applies to all screen sizes */ +.sticky-pricing-card .form-label { + font-size: 1rem; +} + +.sticky-pricing-card .input-group-lg .form-control, +.sticky-pricing-card .input-group-lg .form-select { + font-size: 1rem; + padding: 12px 16px; + min-height: 48px; +} + +/* Style the date input specifically */ +.sticky-pricing-card input[type="date"] { + font-size: 1rem; +} + +/* Make the calendar icon larger on webkit browsers */ +.sticky-pricing-card input[type="date"]::-webkit-calendar-picker-indicator { + width: 20px; + height: 20px; + cursor: pointer; +} + +/* Time select dropdown */ +.sticky-pricing-card .time-select { + font-size: 1rem; +} + +/* Style options in the time dropdown */ +.sticky-pricing-card .time-select option { + font-size: 1rem; + padding: 8px; } \ No newline at end of file diff --git a/frontend/src/components/DeliveryOptions.tsx b/frontend/src/components/DeliveryOptions.tsx deleted file mode 100644 index 4eb877c..0000000 --- a/frontend/src/components/DeliveryOptions.tsx +++ /dev/null @@ -1,60 +0,0 @@ -import React from 'react'; - -interface DeliveryOptionsProps { - pickUpAvailable: boolean; - inPlaceUseAvailable: boolean; - onChange: (e: React.ChangeEvent) => void; -} - -const DeliveryOptions: React.FC = ({ - pickUpAvailable, - inPlaceUseAvailable, - onChange -}) => { - return ( -
-
- -
- - -
-
- - -
-
-
- ); -}; - -export default DeliveryOptions; \ No newline at end of file diff --git a/frontend/src/components/LocationPromptModal.tsx b/frontend/src/components/LocationPromptModal.tsx index 142d2bd..8820d33 100644 --- a/frontend/src/components/LocationPromptModal.tsx +++ b/frontend/src/components/LocationPromptModal.tsx @@ -1,11 +1,10 @@ import React, { useState } from "react"; +import { mapsAPI } from "../services/api"; interface LocationPromptModalProps { show: boolean; onClose: () => void; - onLocationSelect: ( - location: { lat: number; lng: number } | { city?: string; zipCode?: string } - ) => void; + onLocationSelect: (location: { lat: number; lng: number }) => void; } const LocationPromptModal: React.FC = ({ @@ -53,15 +52,31 @@ const LocationPromptModal: React.FC = ({ } }; - const handleManualSubmit = () => { + const handleManualSubmit = async () => { const trimmed = manualLocation.trim(); if (!trimmed) return; - // Check if it looks like a ZIP code - if (/^\d{5}(-\d{4})?$/.test(trimmed)) { - onLocationSelect({ zipCode: trimmed }); - } else { - onLocationSelect({ city: trimmed }); + setLoading(true); + setError(null); + + try { + // Geocode the input (works for both ZIP codes and city names) + const response = await mapsAPI.geocode({ + address: trimmed, + componentRestrictions: { country: "US" }, + }); + + const { latitude, longitude } = response.data; + + if (latitude && longitude) { + onLocationSelect({ lat: latitude, lng: longitude }); + } else { + setError("Could not find that location. Please try a different city or ZIP code."); + } + } catch (err: any) { + setError("Could not find that location. Please try a different city or ZIP code."); + } finally { + setLoading(false); } }; diff --git a/frontend/src/index.css b/frontend/src/index.css index ec2585e..b6bd06d 100644 --- a/frontend/src/index.css +++ b/frontend/src/index.css @@ -1,3 +1,7 @@ +html { + font-size: 20px; +} + body { margin: 0; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', diff --git a/frontend/src/mocks/handlers.ts b/frontend/src/mocks/handlers.ts index 6bdaad0..9142240 100644 --- a/frontend/src/mocks/handlers.ts +++ b/frontend/src/mocks/handlers.ts @@ -48,7 +48,6 @@ export const mockRental = { totalAmount: 25, status: 'pending' as const, paymentStatus: 'pending' as const, - deliveryMethod: 'pickup' as const, createdAt: new Date().toISOString(), updatedAt: new Date().toISOString(), }; diff --git a/frontend/src/pages/CreateItem.tsx b/frontend/src/pages/CreateItem.tsx index 402ca36..5971285 100644 --- a/frontend/src/pages/CreateItem.tsx +++ b/frontend/src/pages/CreateItem.tsx @@ -7,7 +7,6 @@ import AvailabilitySettings from "../components/AvailabilitySettings"; import ImageUpload from "../components/ImageUpload"; import ItemInformation from "../components/ItemInformation"; import LocationForm from "../components/LocationForm"; -import DeliveryOptions from "../components/DeliveryOptions"; import PricingForm from "../components/PricingForm"; import RulesForm from "../components/RulesForm"; import VerificationCodeModal from "../components/VerificationCodeModal"; @@ -17,8 +16,6 @@ import { IMAGE_LIMITS } from "../config/imageLimits"; interface ItemFormData { name: string; description: string; - pickUpAvailable: boolean; - inPlaceUseAvailable: boolean; pricePerHour?: number | string; pricePerDay?: number | string; pricePerWeek?: number | string; @@ -57,8 +54,6 @@ const CreateItem: React.FC = () => { const [formData, setFormData] = useState({ name: "", description: "", - pickUpAvailable: false, - inPlaceUseAvailable: false, pricePerDay: "", replacementCost: "", address1: "", @@ -539,12 +534,6 @@ const CreateItem: React.FC = () => { }} /> - - {/* Availability Card */}
diff --git a/frontend/src/pages/EditItem.tsx b/frontend/src/pages/EditItem.tsx index 94d039a..ee896c5 100644 --- a/frontend/src/pages/EditItem.tsx +++ b/frontend/src/pages/EditItem.tsx @@ -8,7 +8,6 @@ import AvailabilitySettings from "../components/AvailabilitySettings"; import ImageUpload from "../components/ImageUpload"; import ItemInformation from "../components/ItemInformation"; import LocationForm from "../components/LocationForm"; -import DeliveryOptions from "../components/DeliveryOptions"; import PricingForm from "../components/PricingForm"; import RulesForm from "../components/RulesForm"; import { IMAGE_LIMITS } from "../config/imageLimits"; @@ -16,8 +15,6 @@ import { IMAGE_LIMITS } from "../config/imageLimits"; interface ItemFormData { name: string; description: string; - pickUpAvailable: boolean; - inPlaceUseAvailable: boolean; pricePerHour?: number | string; pricePerDay?: number | string; pricePerWeek?: number | string; @@ -78,8 +75,6 @@ const EditItem: React.FC = () => { const [formData, setFormData] = useState({ name: "", description: "", - pickUpAvailable: false, - inPlaceUseAvailable: false, pricePerHour: "", pricePerDay: "", replacementCost: "", @@ -135,8 +130,6 @@ const EditItem: React.FC = () => { setFormData({ name: item.name, description: item.description, - pickUpAvailable: item.pickUpAvailable || false, - inPlaceUseAvailable: item.inPlaceUseAvailable || false, pricePerHour: item.pricePerHour || "", pricePerDay: item.pricePerDay || "", pricePerWeek: item.pricePerWeek || "", @@ -578,12 +571,6 @@ const EditItem: React.FC = () => { }} /> - - {
{ <>
-
- -
+
+ +
{ style={{ flex: "1 1 50%" }} /> { style={{ flex: "1 1 50%" }} />