Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions src/components/ui/apple-cards-carousel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -235,19 +235,19 @@ export const Card = ({
className="relative z-10 flex h-[60vh] w-[70vw] flex-col items-start justify-start overflow-hidden rounded-3xl bg-gray-100 md:h-[40rem] md:w-96 dark:bg-neutral-900 hover:cursor-pointer"
>
<div className="pointer-events-none absolute inset-x-0 top-0 z-30 h-full bg-gradient-to-b from-black/50 via-transparent to-transparent" />
<div className="relative z-40 p-8">
<div className="relative z-40 p-8 flex flex-col items-start">
<motion.p
layoutId={layout ? `title-${card.title}` : undefined}
className="mt-4 max-w-xs text-left text-xl font-semibold [text-wrap:balance] text-white md:text-3xl"
>
{card.title}
</motion.p>
{card.special && <motion.div
{card.special && <motion.p
layoutId={layout ? `category-${card.special}` : undefined}
className="inline-block mt-2 px-3 py-1 bg-gradient-to-r from-purple-500 to-indigo-500 rounded-full text-sm font-semibold text-white shadow-lg md:text-base"
>
{card.special}
</motion.div>}
</motion.p>}
<motion.p
layoutId={layout ? `date-${card.date}` : undefined}
className="mt-1 text-left text-sm font-medium text-white md:text-lg"
Expand Down
78 changes: 23 additions & 55 deletions src/features/carpool/components/Carpool.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,16 @@ import CarpoolModal from "./CarpoolModal";
import CarpoolInboxModal from "./CarpoolInboxModal";
import CarpoolCard from "./CarpoolCard";
import { useAuthContext } from "@/hooks/useAuthContext";
import { CarpoolTypeEnum } from "../enums/CarpoolTypeEnum";
import NoCarpoolsAvailable from "./ui/NoCarpoolsAvailable";
import CarpoolLoadingPlaceholder from "./ui/CarpoolLoadingPlaceholder";

export default function Carpool() {
const yesterday = new Date();
yesterday.setDate(yesterday.getDate() - 1);
const { documents: carpools } = useCollection<CarpoolPost>(collections.carpoolCollection, ['targetDate', '>=', yesterday], ['targetDate', 'asc'], true);
const [isCreateModalOpen, setIsCreateModalOpen] = useState(false);
const [createModalType, setCreateModalType] = useState<CarpoolTypeEnum>(CarpoolTypeEnum.Carpool);
const [isInboxModalOpen, setIsInboxModalOpen] = useState(false);
const { user: currentUser } = useAuthContext();

Expand Down Expand Up @@ -70,6 +74,11 @@ export default function Carpool() {
}, 0);
}, [carpools, currentUser]);

const handleOpenCreateModal = (type: CarpoolTypeEnum) => {
setCreateModalType(type);
setIsCreateModalOpen(true);
}

// Render a section of carpools
const renderCarpoolSection = (title: string, carpools: CarpoolPost[], ownershipType?: 'owner' | 'member' | 'requested') => {
if (carpools.length === 0) return null;
Expand All @@ -82,7 +91,7 @@ export default function Carpool() {
{carpools.length}
</span>
</div>
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 2xl:grid-cols-5 gap-4 sm:gap-6">
<div className="grid grid-cols-1 sm:grid-cols-2 xl:grid-cols-3 2xl:grid-cols-4 gap-4 sm:gap-6">
{carpools.map((carpool) => (
<CarpoolCard
key={carpool.id}
Expand Down Expand Up @@ -118,11 +127,18 @@ export default function Carpool() {
</button>
)}
<button
onClick={() => setIsCreateModalOpen(true)}
onClick={() => handleOpenCreateModal(CarpoolTypeEnum.UberSplit)}
className="inline-flex items-center gap-2 px-4 py-2 bg-gradient-to-r from-pink-500 to-purple-600 text-white rounded-xl font-medium hover:from-pink-600 hover:to-purple-700 transition-all duration-200 transform hover:scale-[1.02] active:scale-[0.98] shadow-lg"
>
<IconPlus size={18} />
Split an Uber
</button>
<button
onClick={() => handleOpenCreateModal(CarpoolTypeEnum.Carpool)}
className="inline-flex items-center gap-2 px-4 py-2 bg-gradient-to-r from-emerald-500 to-teal-600 text-white rounded-xl font-medium hover:from-emerald-600 hover:to-teal-700 transition-all duration-200 transform hover:scale-[1.02] active:scale-[0.98] shadow-lg"
>
<IconPlus size={18} />
Create Carpool
Drive People
</button>
<div className="flex items-center gap-2 text-sm text-slate-500 dark:text-slate-400">
<div className="w-2 h-2 bg-green-500 rounded-full animate-pulse"></div>
Expand Down Expand Up @@ -168,70 +184,22 @@ export default function Carpool() {
categorizedCarpools.joinedCarpools.length === 0 &&
categorizedCarpools.requestedCarpools.length === 0 &&
categorizedCarpools.availableCarpools.length === 0 && (
<div className="flex flex-col items-center justify-center py-16 px-4">
<div className="w-24 h-24 bg-gradient-to-br from-slate-200 to-slate-300 dark:from-slate-700 dark:to-slate-600 rounded-full flex items-center justify-center mb-6">
<div className="w-12 h-12 bg-slate-400 dark:bg-slate-500 rounded-full"></div>
</div>
<h3 className="text-xl font-semibold text-slate-600 dark:text-slate-300 mb-2">No Carpools Available</h3>
<p className="text-slate-500 dark:text-slate-400 text-center max-w-md mb-6">
There are currently no carpools scheduled. Check back later or create your own!
</p>
<button
onClick={() => setIsCreateModalOpen(true)}
className="inline-flex items-center gap-2 px-6 py-3 bg-gradient-to-r from-emerald-500 to-teal-600 text-white rounded-xl font-medium hover:from-emerald-600 hover:to-teal-700 transition-all duration-200 transform hover:scale-[1.02] active:scale-[0.98] shadow-lg"
>
<IconPlus size={18} />
Create First Carpool
</button>
</div>
<NoCarpoolsAvailable />
)}
</div>
) : (
<div className="flex flex-col items-center justify-center py-16 px-4">
<div className="w-24 h-24 bg-gradient-to-br from-slate-200 to-slate-300 dark:from-slate-700 dark:to-slate-600 rounded-full flex items-center justify-center mb-6">
<div className="w-12 h-12 bg-slate-400 dark:bg-slate-500 rounded-full"></div>
</div>
<h3 className="text-xl font-semibold text-slate-600 dark:text-slate-300 mb-2">No Carpools Available</h3>
<p className="text-slate-500 dark:text-slate-400 text-center max-w-md mb-6">
There are currently no carpools scheduled. Check back later or create your own!
</p>
<button
onClick={() => setIsCreateModalOpen(true)}
className="inline-flex items-center gap-2 px-6 py-3 bg-gradient-to-r from-emerald-500 to-teal-600 text-white rounded-xl font-medium hover:from-emerald-600 hover:to-teal-700 transition-all duration-200 transform hover:scale-[1.02] active:scale-[0.98] shadow-lg"
>
<IconPlus size={18} />
Create First Carpool
</button>
</div>
<NoCarpoolsAvailable />
)
) : (
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 2xl:grid-cols-5 gap-4 sm:gap-6">
{[...Array(8)].map((_, index) => (
<div key={index} className="rounded-2xl bg-gradient-to-br from-slate-100 to-slate-200 dark:from-slate-800 dark:to-slate-700 p-6 animate-pulse">
<div className="space-y-4">
<div className="flex justify-between items-start">
<div className="space-y-2 flex-1">
<div className="h-5 bg-slate-300 dark:bg-slate-600 rounded w-3/4"></div>
<div className="h-3 bg-slate-300 dark:bg-slate-600 rounded w-1/2"></div>
</div>
<div className="h-6 w-16 bg-slate-300 dark:bg-slate-600 rounded-full"></div>
</div>
<div className="space-y-2">
<div className="h-3 bg-slate-300 dark:bg-slate-600 rounded w-full"></div>
<div className="h-3 bg-slate-300 dark:bg-slate-600 rounded w-4/5"></div>
</div>
<div className="h-10 bg-slate-300 dark:bg-slate-600 rounded-xl"></div>
</div>
</div>
))}
</div>
<CarpoolLoadingPlaceholder />
)}
</div>
</div>

{/* Create Carpool Modal */}
<CarpoolModal
isOpen={isCreateModalOpen}
type={createModalType}
onClose={() => setIsCreateModalOpen(false)}
// onSuccess={handleCreateSuccess}
/>
Expand Down
10 changes: 9 additions & 1 deletion src/features/carpool/components/CarpoolCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import collections from "@/firebase/collections";
import { useCachedDocument } from "@/hooks/useCachedDocument";
import { IconCrown, IconUser, IconClock } from "@tabler/icons-react";
import { CarpoolStatusEnum } from "../enums/CarpoolStatusEnum";
import { CarpoolTypeEnum } from "../enums/CarpoolTypeEnum";

interface CarpoolCardProps {
carpool: CarpoolPost;
Expand Down Expand Up @@ -62,16 +63,23 @@ export default function CarpoolCard({ carpool, ownershipType }: CarpoolCardProps
}`}>
{carpool.status === CarpoolStatusEnum.Closed ? 'Closed' : `${carpool.maxPeople - carpool.people.length} seats`}
</span>

</div>
</div>

<div className="space-y-3 mb-6">
<div className="flex items-center gap-2">
<div className="w-2 h-2 bg-indigo-500 rounded-full"></div>
<span className="text-sm text-slate-600 dark:text-slate-300">
<span className="font-medium">Driver:</span> {user ? (user.displayName || user.email || 'Unknown') : carpool.userId}
<span className="font-medium">Creator:</span> {user ? (user.displayName || user.email || 'Unknown') : carpool.userId}
</span>
</div>
<div className="flex items-center gap-2">
<div className="w-2 h-2 bg-emerald-500 rounded-full"></div>
<span className="text-sm text-slate-600 dark:text-slate-300">
<span className="font-medium">Type:</span> {carpool.type === CarpoolTypeEnum.Carpool ? 'Carpool' : 'Uber Split'}
</span>
</div>
<div className="flex items-center gap-2">
<div className="w-2 h-2 bg-purple-500 rounded-full"></div>
<span className="text-sm text-slate-600 dark:text-slate-300">
Expand Down
12 changes: 7 additions & 5 deletions src/features/carpool/components/CarpoolDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { db } from "@/firebase/config";
import collections from "@/firebase/collections";
import { useState } from "react";
import CarpoolModal from "./CarpoolModal";
import { CarpoolTypeEnum } from "../enums/CarpoolTypeEnum";

export default function CarpoolDetails() {
const { id } = useParams<{ id: string }>();
Expand Down Expand Up @@ -626,7 +627,7 @@ export default function CarpoolDetails() {
</button>
<div>
<h1 className="font-bold text-transparent bg-clip-text bg-indigo-600 text-2xl sm:text-3xl lg:text-4xl">
Carpool Details
{carpool.type === CarpoolTypeEnum.Carpool ? 'Carpool Details' : 'Uber Split Details'}
</h1>
<p className="text-slate-500 dark:text-slate-400 mt-1">
Review and join this carpool
Expand Down Expand Up @@ -779,7 +780,7 @@ export default function CarpoolDetails() {
<div className="p-2 rounded-lg bg-emerald-500/20">
<IconUser className="text-emerald-600 dark:text-emerald-400" size={24} />
</div>
<h2 className="text-lg font-semibold text-slate-800 dark:text-slate-100">Driver</h2>
<h2 className="text-lg font-semibold text-slate-800 dark:text-slate-100">Creator</h2>
</div>

<div className="text-center">
Expand Down Expand Up @@ -811,10 +812,10 @@ export default function CarpoolDetails() {
</div>
)}
</div>
<div className="inline-flex items-center gap-1 px-2 py-1 bg-emerald-100 dark:bg-emerald-900/30 text-emerald-700 dark:text-emerald-300 rounded-full text-xs font-medium">
{carpool.type === CarpoolTypeEnum.Carpool && (<div className="inline-flex items-center gap-1 px-2 py-1 bg-emerald-100 dark:bg-emerald-900/30 text-emerald-700 dark:text-emerald-300 rounded-full text-xs font-medium">
<IconUser size={14} />
Driver
</div>
</div>)}
</div>
</div>

Expand Down Expand Up @@ -963,7 +964,7 @@ export default function CarpoolDetails() {
: 'bg-slate-100 text-slate-600 dark:bg-slate-700/50 dark:text-slate-400'
}`}>
{carpool.userId === currentUser.uid
? '🚗 You are the driver of this carpool'
? 'You are the creator of this carpool'
: carpool.people.includes(currentUser.uid)
? '✅ You are part of this carpool'
: '👤 You are not part of this carpool'}
Expand Down Expand Up @@ -1087,6 +1088,7 @@ export default function CarpoolDetails() {
{/* Edit Carpool Modal */}
<CarpoolModal
isOpen={isEditModalOpen}
type={carpool.type}
onClose={() => setIsEditModalOpen(false)}
carpool={carpool}
onSuccess={handleEditSuccess}
Expand Down
19 changes: 14 additions & 5 deletions src/features/carpool/components/CarpoolModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,17 @@ import { db } from "@/firebase/config";
import collections from "@/firebase/collections";
import { CarpoolStatusEnum } from "../enums/CarpoolStatusEnum";
import CarpoolPost from "../interfaces/CarpoolPost";
import { CarpoolTypeEnum } from "../enums/CarpoolTypeEnum";

interface CarpoolModalProps {
isOpen: boolean;
type?: CarpoolTypeEnum;
onClose: () => void;
carpool?: CarpoolPost | null; // If provided, it's edit mode
onSuccess?: () => void;
}

export default function CarpoolModal({ isOpen, onClose, carpool }: CarpoolModalProps) {
export default function CarpoolModal({ isOpen, type, onClose, carpool }: CarpoolModalProps) {
const { user } = useAuthContext();
const [isSubmitting, setIsSubmitting] = useState(false);
const [message, setMessage] = useState<{ text: string; type: 'success' | 'error' } | null>(null);
Expand Down Expand Up @@ -95,6 +97,7 @@ export default function CarpoolModal({ isOpen, onClose, carpool }: CarpoolModalP

const carpoolData = {
location: formData.location,
type: type || CarpoolTypeEnum.Carpool,
destination: formData.destination,
targetDate: timestamp,
maxPeople: formData.maxPeople,
Expand Down Expand Up @@ -136,9 +139,15 @@ export default function CarpoolModal({ isOpen, onClose, carpool }: CarpoolModalP
<div className="bg-white dark:bg-slate-800 rounded-2xl shadow-2xl w-full max-w-2xl max-h-[90vh] overflow-y-auto">
<div className="sticky top-0 bg-white dark:bg-slate-800 border-b border-slate-200 dark:border-slate-700 p-6 rounded-t-2xl">
<div className="flex items-center justify-between">
<h2 className="text-2xl font-bold text-slate-800 dark:text-slate-100">
{isEditMode ? 'Edit Carpool' : 'Create New Carpool'}
</h2>
{type === CarpoolTypeEnum.UberSplit ? (
<h2 className="text-2xl font-bold text-slate-800 dark:text-slate-100">
{isEditMode ? 'Edit Uber Split' : 'Split an Uber'}
</h2>
) : (
<h2 className="text-2xl font-bold text-slate-800 dark:text-slate-100">
{isEditMode ? 'Edit Carpool' : 'Create New Carpool'}
</h2>
)}
<button
onClick={onClose}
className="p-2 rounded-lg hover:bg-slate-100 dark:hover:bg-slate-700 transition-colors"
Expand Down Expand Up @@ -301,7 +310,7 @@ export default function CarpoolModal({ isOpen, onClose, carpool }: CarpoolModalP
>
{isSubmitting
? (isEditMode ? 'Updating...' : 'Creating...')
: (isEditMode ? 'Update Carpool' : 'Create Carpool')}
: (type === CarpoolTypeEnum.UberSplit ? (isEditMode ? 'Update Uber Split' : 'Create Uber Split') : (isEditMode ? 'Update Carpool' : 'Create Carpool'))}
</button>
</div>
</form>
Expand Down
24 changes: 24 additions & 0 deletions src/features/carpool/components/ui/CarpoolLoadingPlaceholder.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
export default function CarpoolLoadingPlaceholder() {
return (
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 2xl:grid-cols-5 gap-4 sm:gap-6">
{[...Array(8)].map((_, index) => (
<div key={index} className="rounded-2xl bg-gradient-to-br from-slate-100 to-slate-200 dark:from-slate-800 dark:to-slate-700 p-6 animate-pulse">
<div className="space-y-4">
<div className="flex justify-between items-start">
<div className="space-y-2 flex-1">
<div className="h-5 bg-slate-300 dark:bg-slate-600 rounded w-3/4"></div>
<div className="h-3 bg-slate-300 dark:bg-slate-600 rounded w-1/2"></div>
</div>
<div className="h-6 w-16 bg-slate-300 dark:bg-slate-600 rounded-full"></div>
</div>
<div className="space-y-2">
<div className="h-3 bg-slate-300 dark:bg-slate-600 rounded w-full"></div>
<div className="h-3 bg-slate-300 dark:bg-slate-600 rounded w-4/5"></div>
</div>
<div className="h-10 bg-slate-300 dark:bg-slate-600 rounded-xl"></div>
</div>
</div>
))}
</div>
)
}
13 changes: 13 additions & 0 deletions src/features/carpool/components/ui/NoCarpoolsAvailable.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
export default function NoCarpoolsAvailable() {
return (
<div className="flex flex-col items-center justify-center py-16 px-4">
<div className="w-24 h-24 bg-gradient-to-br from-slate-200 to-slate-300 dark:from-slate-700 dark:to-slate-600 rounded-full flex items-center justify-center mb-6">
<div className="w-12 h-12 bg-slate-400 dark:bg-slate-500 rounded-full"></div>
</div>
<h3 className="text-xl font-semibold text-slate-600 dark:text-slate-300 mb-2">No Carpools Available</h3>
<p className="text-slate-500 dark:text-slate-400 text-center max-w-md mb-6">
There are currently no carpools scheduled. Check back later or create your own!
</p>
</div>
)
}
4 changes: 4 additions & 0 deletions src/features/carpool/enums/CarpoolTypeEnum.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export enum CarpoolTypeEnum {
Carpool = 'Carpool',
UberSplit = 'UberSplit',
}
2 changes: 2 additions & 0 deletions src/features/carpool/interfaces/CarpoolPost.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { CarpoolStatusEnum } from "../enums/CarpoolStatusEnum";
import { Timestamp } from "firebase/firestore";
import { CarpoolTypeEnum } from "../enums/CarpoolTypeEnum";


export default interface CarpoolPost {
Expand All @@ -10,6 +11,7 @@ export default interface CarpoolPost {
description: string;
maxPeople: number;
carType: string;
type: CarpoolTypeEnum;
status: CarpoolStatusEnum;
people: string[];
requests: string[]; // Array of user IDs who have requested to join
Expand Down