started dockerfiles and itemrequest

This commit is contained in:
jackiettran
2025-08-18 12:24:46 -04:00
parent 209d8f5fbf
commit 99eae4774e
18 changed files with 2080 additions and 1 deletions

View File

@@ -0,0 +1,303 @@
import React, { useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { useAuth } from '../contexts/AuthContext';
import { itemRequestAPI } from '../services/api';
import AddressAutocomplete from '../components/AddressAutocomplete';
const CreateItemRequest: React.FC = () => {
const navigate = useNavigate();
const { user } = useAuth();
const [loading, setLoading] = useState(false);
const [error, setError] = useState<string | null>(null);
const [formData, setFormData] = useState({
title: '',
description: '',
address1: '',
address2: '',
city: '',
state: '',
zipCode: '',
country: 'US',
latitude: undefined as number | undefined,
longitude: undefined as number | undefined,
maxPricePerHour: '',
maxPricePerDay: '',
preferredStartDate: '',
preferredEndDate: '',
isFlexibleDates: true
});
const handleChange = (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement>) => {
const { name, value, type } = e.target;
if (type === 'checkbox') {
const checked = (e.target as HTMLInputElement).checked;
setFormData(prev => ({ ...prev, [name]: checked }));
} else {
setFormData(prev => ({ ...prev, [name]: value }));
}
};
const handleAddressChange = (value: string, lat?: number, lon?: number) => {
setFormData(prev => ({
...prev,
address1: value,
latitude: lat,
longitude: lon,
city: prev.city,
state: prev.state,
zipCode: prev.zipCode,
country: prev.country
}));
};
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
if (!user) return;
setLoading(true);
setError(null);
try {
const requestData = {
...formData,
maxPricePerHour: formData.maxPricePerHour ? parseFloat(formData.maxPricePerHour) : null,
maxPricePerDay: formData.maxPricePerDay ? parseFloat(formData.maxPricePerDay) : null,
preferredStartDate: formData.preferredStartDate || null,
preferredEndDate: formData.preferredEndDate || null
};
await itemRequestAPI.createItemRequest(requestData);
navigate('/my-requests');
} catch (err: any) {
setError(err.response?.data?.error || 'Failed to create item request');
setLoading(false);
}
};
if (!user) {
return (
<div className="container mt-5">
<div className="alert alert-warning" role="alert">
Please log in to create item requests.
</div>
</div>
);
}
return (
<div className="container mt-4">
<div className="row justify-content-center">
<div className="col-md-8">
<div className="card">
<div className="card-header">
<h2 className="mb-0">Request an Item</h2>
<p className="text-muted mb-0">Can't find what you need? Request it and let others know!</p>
</div>
<div className="card-body">
{error && (
<div className="alert alert-danger" role="alert">
{error}
</div>
)}
<form onSubmit={handleSubmit}>
<div className="mb-3">
<label htmlFor="title" className="form-label">What are you looking for? *</label>
<input
type="text"
className="form-control"
id="title"
name="title"
value={formData.title}
onChange={handleChange}
placeholder="e.g., Power drill, Camera lens, Camping tent"
required
/>
</div>
<div className="mb-3">
<label htmlFor="description" className="form-label">Description *</label>
<textarea
className="form-control"
id="description"
name="description"
rows={4}
value={formData.description}
onChange={handleChange}
placeholder="Describe what you need it for, any specific requirements, condition preferences, etc."
required
/>
</div>
<div className="row mb-3">
<div className="col-md-6">
<label htmlFor="maxPricePerDay" className="form-label">Max Price per Day</label>
<div className="input-group">
<span className="input-group-text">$</span>
<input
type="number"
className="form-control"
id="maxPricePerDay"
name="maxPricePerDay"
value={formData.maxPricePerDay}
onChange={handleChange}
step="0.01"
min="0"
placeholder="0.00"
/>
</div>
</div>
<div className="col-md-6">
<label htmlFor="maxPricePerHour" className="form-label">Max Price per Hour</label>
<div className="input-group">
<span className="input-group-text">$</span>
<input
type="number"
className="form-control"
id="maxPricePerHour"
name="maxPricePerHour"
value={formData.maxPricePerHour}
onChange={handleChange}
step="0.01"
min="0"
placeholder="0.00"
/>
</div>
</div>
</div>
<div className="mb-3">
<label className="form-label">Address</label>
<AddressAutocomplete
value={formData.address1}
onChange={handleAddressChange}
placeholder="Enter your address or area"
/>
</div>
<div className="row mb-3">
<div className="col-md-6">
<label htmlFor="address2" className="form-label">Apartment, suite, etc.</label>
<input
type="text"
className="form-control"
id="address2"
name="address2"
value={formData.address2}
onChange={handleChange}
placeholder="Apt 2B, Suite 100, etc."
/>
</div>
<div className="col-md-6">
<label htmlFor="city" className="form-label">City</label>
<input
type="text"
className="form-control"
id="city"
name="city"
value={formData.city}
onChange={handleChange}
placeholder="City"
/>
</div>
</div>
<div className="row mb-3">
<div className="col-md-6">
<label htmlFor="state" className="form-label">State</label>
<input
type="text"
className="form-control"
id="state"
name="state"
value={formData.state}
onChange={handleChange}
placeholder="State"
/>
</div>
<div className="col-md-6">
<label htmlFor="zipCode" className="form-label">ZIP Code</label>
<input
type="text"
className="form-control"
id="zipCode"
name="zipCode"
value={formData.zipCode}
onChange={handleChange}
placeholder="12345"
/>
</div>
</div>
<div className="mb-3">
<div className="form-check">
<input
className="form-check-input"
type="checkbox"
id="isFlexibleDates"
name="isFlexibleDates"
checked={formData.isFlexibleDates}
onChange={handleChange}
/>
<label className="form-check-label" htmlFor="isFlexibleDates">
I'm flexible with dates
</label>
</div>
</div>
{!formData.isFlexibleDates && (
<div className="row mb-3">
<div className="col-md-6">
<label htmlFor="preferredStartDate" className="form-label">Preferred Start Date</label>
<input
type="date"
className="form-control"
id="preferredStartDate"
name="preferredStartDate"
value={formData.preferredStartDate}
onChange={handleChange}
min={new Date().toISOString().split('T')[0]}
/>
</div>
<div className="col-md-6">
<label htmlFor="preferredEndDate" className="form-label">Preferred End Date</label>
<input
type="date"
className="form-control"
id="preferredEndDate"
name="preferredEndDate"
value={formData.preferredEndDate}
onChange={handleChange}
min={formData.preferredStartDate || new Date().toISOString().split('T')[0]}
/>
</div>
</div>
)}
<div className="d-grid gap-2">
<button
type="submit"
className="btn btn-primary"
disabled={loading}
>
{loading ? 'Creating Request...' : 'Create Request'}
</button>
<button
type="button"
className="btn btn-secondary"
onClick={() => navigate(-1)}
>
Cancel
</button>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
);
};
export default CreateItemRequest;