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
2 changes: 1 addition & 1 deletion app/auth/callback/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export async function GET(request: NextRequest) {
const requestUrl = new URL(request.url);
const code = requestUrl.searchParams.get('code');
const type = requestUrl.searchParams.get('type');
const next = requestUrl.searchParams.get('next') || '/settings';
const next = requestUrl.searchParams.get('next') || '/';

// If this is an email confirmation, redirect to the confirmation page
if (type === 'signup') {
Expand Down
1 change: 0 additions & 1 deletion app/browse/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
import React, { useEffect, useState, useRef, Suspense } from "react";
import { motion } from "framer-motion";
import { useSearchParams } from "next/navigation";
import { supabase } from "../lib/supabaseClient";
import SearchBar from "./components/SearchBar";
import ListingCard from "./components/ListingCard";
import * as timeago from "timeago.js";
Expand Down
4 changes: 0 additions & 4 deletions app/create/components/ImageUpload.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,6 @@ const ImageUpload: React.FC<ImageUploadProps> = ({
onChange={handleFileChange}
/>
</div>
<button className="flex items-center gap-2 px-4 py-2 border rounded-md shadow-sm text-sm bg-white hover:bg-gray-100 transition">
<UploadCloud size={16} />
Upload Photos
</button>
</div>
);
};
Expand Down
9 changes: 7 additions & 2 deletions app/create/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,6 @@ const Create = () => {
setImages((prev) => prev.filter((_, i) => i !== index));
};


const handleSaveDraft = async () => {
if (!user?.id) {
toast.error("You must be logged in to save a draft.");
Expand Down Expand Up @@ -232,6 +231,7 @@ const Create = () => {
className="w-full border rounded-md px-3 py-2 text-sm"
value={title}
onChange={(e) => setTitle(e.target.value)}
required
/>
</div>

Expand All @@ -245,6 +245,7 @@ const Create = () => {
className="w-full border rounded-md px-3 py-2 text-sm"
value={category}
onChange={(e) => setCategory(e.target.value)}
required
>
<option>Select a category</option>
<option>Furniture</option>
Expand Down Expand Up @@ -282,6 +283,7 @@ const Create = () => {
onBlur={() => {
if (price < 0.01) setPrice(0.01);
}}
required
/>
</div>
{price < 0.01 && (
Expand All @@ -299,6 +301,7 @@ const Create = () => {
className="w-full border rounded-md px-3 py-2 text-sm"
value={condition}
onChange={(e) => setCondition(e.target.value)}
required
>
<option>Select condition</option>
<option>New</option>
Expand All @@ -317,9 +320,10 @@ const Create = () => {
<input
type="text"
className="w-full border rounded-md px-3 py-2 text-sm mb-2"
placeholder="Enter a location name (optional, e.g. West Campus)"
placeholder="Enter a location name (e.g. West Campus)"
value={location}
onChange={(e) => setLocation(e.target.value)}
required
/>
<div className="my-2">
<MapPicker
Expand Down Expand Up @@ -349,6 +353,7 @@ const Create = () => {
placeholder="Describe your item..."
value={description}
onChange={(e) => setDescription(e.target.value)}
required
/>
</div>

Expand Down
13 changes: 8 additions & 5 deletions app/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,24 @@
import type { Metadata } from "next";
import { Inter, Roboto } from "next/font/google";
import { Inter, Roboto_Flex } from "next/font/google";
import "./globals.css";
import Navbar from "../components/globals/Navbar";
import { AuthProvider } from './context/AuthContext';
import FooterWrapper from "../components/globals/FooterWrapper";
import AdminRedirectWrapper from "../components/layout/AdminRedirectWrapper";

// Using Roboto as a fallback since it's similar to Benton Sans
const roboto = Roboto({
// Using Roboto Flex for better typography flexibility
const robotoFlex = Roboto_Flex({
subsets: ["latin"],
weight: ["100", "300", "400", "500", "700", "900"],
weight: ["100", "200", "300", "400", "500", "600", "700", "800", "900"],
variable: "--font-sans",
});

export const metadata: Metadata = {
title: "UT Marketplace",
description: "Buy and sell items within the UT community",
icons: {
icon: "/icons/ios-light.png",
},
};

export default function RootLayout({
Expand All @@ -24,7 +27,7 @@ export default function RootLayout({
children: React.ReactNode;
}) {
return (
<html lang="en" className={roboto.variable}>
<html lang="en" className={robotoFlex.variable}>
<body className="font-sans">
<div className="flex flex-col min-h-screen">
<AuthProvider>
Expand Down
40 changes: 26 additions & 14 deletions app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
"use client"
import React, { useEffect, useState } from "react";
import { motion, AnimatePresence } from "framer-motion";
import Hero from "../components/home/Hero";
import Testomonials from "../components/home/Testomonials";
import RecentListings from "../components/home/Recents";
import CategorySection from "../components/home/CategorySection";
import { ShieldCheck, Zap, MessageCircle, Users, Star, CheckCircle, Flame, TrendingUp, Smile } from 'lucide-react';
import { ShieldCheck, Zap, MessageCircle, Users, Star, CheckCircle } from 'lucide-react';
import BetaPopup from '../components/home/BetaPopup';
import { FaPlus, FaSearch } from "react-icons/fa";
import { motion, AnimatePresence } from "framer-motion";
import Link from "next/link";

const itemVariants = {
hidden: { opacity: 0, y: 30 },
visible: { opacity: 1, y: 0, transition: { duration: 0.7, ease: 'easeOut' } },
};

const LiveTicker = () => {
const [messages] = useState([
Expand Down Expand Up @@ -92,17 +99,27 @@ const HowItWorks = () => (

const CallToActionBanner = () => (
<section className="relative py-8 px-4 md:px-0">
<div className="max-w-4xl mx-auto bg-gradient-to-r from-[#bf5700] to-orange-400 rounded-2xl shadow-lg flex flex-col md:flex-row items-center justify-between gap-6 p-8 text-white">
<div className="max-w-4xl mx-auto bg-ut-orange rounded-2xl shadow-lg flex flex-col md:flex-row items-center justify-between gap-6 p-8 text-white">
<div className="flex-1">
<h2 className="text-2xl md:text-3xl font-bold mb-2">Ready to make a deal?</h2>
<p className="text-lg mb-4">Create a listing or browse hundreds of items from fellow Longhorns!</p>
<div className="flex gap-4">
<a href="/create" className="bg-white text-[#bf5700] font-semibold px-6 py-2 rounded-lg shadow hover:bg-orange-100 transition">Create Listing</a>
<a href="/browse" className="bg-[#bf5700] border border-white font-semibold px-6 py-2 rounded-lg hover:bg-orange-600 transition">Browse Items</a>
</div>
<motion.div variants={itemVariants} className="flex flex-col sm:flex-row gap-4 w-full sm:w-auto justify-center md:justify-start">
<Link
href="/create"
className="flex items-center justify-center bg-ut-orange text-white px-6 py-3 rounded-lg font-semibold text-lg transition-all duration-300 hover:scale-105 hover:-translate-y-1 border-1 border-ut-white"
>
<FaPlus className="mr-2" />
Create Listing
</Link>
<Link
href="/browse"
className="flex items-center justify-center px-6 py-3 rounded-lg font-semibold text-lg transition-all duration-300 bg-white text-ut-orange shadow-md hover:scale-105 hover:-translate-y-1"
>
<FaSearch className="mr-2" /> Browse Items
</Link>
</motion.div>
</div>
<Mascot />
<ShieldCheck className="w-24 h-24 text-white/80 hidden md:block" />
</div>
</section>
);
Expand All @@ -116,12 +133,7 @@ const SafetyBadge = () => (

const Home = () => {
return (
<div className="relative bg-gradient-to-br from-orange-100 via-white overflow-hidden">
{/* Background Pattern or Overlay */}
<div
className="absolute inset-0 bg-[url('/pattern.jpg')] opacity-30 pointer-events-none"
aria-hidden="true"
/>
<div className="relative overflow-hidden">
<div className="relative z-10">
<Hero />
<LiveTicker />
Expand Down
12 changes: 6 additions & 6 deletions components/globals/Footer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,9 @@ const Footer = () => {
<li key={category.name}>
<button
onClick={() => handleCategoryClick(category.name)}
className="flex items-center gap-2 text-sm hover:text-[#d95e00] transition cursor-pointer"
className="flex items-center gap-2 text-sm hover:text-ut-orange transition cursor-pointer"
>
<div className="w-5 h-5 flex items-center justify-center text-[#d95e00]">
<div className="w-5 h-5 flex items-center justify-center text-ut-orange">
<category.icon className="h-4 w-4" />
</div>
{category.name}
Expand All @@ -60,22 +60,22 @@ const Footer = () => {
<h3 className="text-sm font-semibold tracking-wider uppercase">Support</h3>
<ul className="mt-4 space-y-2">
<li>
<Link href="/help" className="text-sm hover:text-[#d95e00]">
<Link href="/help" className="text-sm hover:text-ut-orange">
Help Center
</Link>
</li>
<li>
<Link href="/safety" className="text-sm hover:text-[#d95e00]">
<Link href="/safety" className="text-sm hover:text-ut-orange">
Safety Tips
</Link>
</li>
<li>
<Link href="/terms" className="text-sm hover:text-[#d95e00]">
<Link href="/terms" className="text-sm hover:text-ut-orange">
Terms of Service
</Link>
</li>
<li>
<Link href="/privacy" className="text-sm hover:text-[#d95e00]">
<Link href="/privacy" className="text-sm hover:text-ut-orange">
Privacy Policy
</Link>
</li>
Expand Down
5 changes: 3 additions & 2 deletions components/globals/Navbar.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"use client";
import Link from "next/link";
import { useState, useRef, useEffect } from "react";
import { MessageCircle, Settings, LogOut, Plus, X, User, Menu, Heart, Shield } from "lucide-react";
import { MessageCircle, Settings, LogOut, Plus, X, User, Menu, Heart } from "lucide-react";
import { useAuth } from "../../app/context/AuthContext";
import Notifications from "./Notifications";

Expand Down Expand Up @@ -123,9 +123,10 @@ const Navbar = () => {
) : (
<Link
href="/auth/signin"
className="text-white hover:text-white/80 transition font-semibold"
className="text-white hover:text-white transition duration-100 font-semibold relative group hover:scale-110"
>
Sign In
<span className="absolute bottom-0 left-0 w-0 h-0.5 bg-white group-hover:w-full transition-all duration-300" />
</Link>
)}
</div>
Expand Down
4 changes: 2 additions & 2 deletions components/home/CategorySection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@ const CategorySection = () => {
<button
key={category.name}
onClick={() => handleCategoryClick(category.name)}
className="flex flex-col items-center justify-center p-4 bg-white rounded-xl shadow-sm hover:shadow-lg hover:-translate-y-1 transition-all duration-300 ease-in-out border border-gray-100"
className="flex flex-col items-center justify-center p-4 bg-white rounded-xl shadow-sm hover:shadow-lg hover:-translate-y-1 transition-all duration-300 ease-in-out border border-gray-100 cursor-pointer"
>
<div className="w-12 h-12 flex items-center justify-center bg-orange-100 text-orange-600 rounded-full mb-3">
<div className="w-12 h-12 flex items-center justify-center bg-ut-orange text-white rounded-full mb-3">
<category.icon className="h-6 w-6" />
</div>
<span className="text-sm font-medium text-gray-700">{category.name}</span>
Expand Down
13 changes: 3 additions & 10 deletions components/home/Hero.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -136,26 +136,19 @@ const Hero = () => {
<motion.div variants={itemVariants} className="flex flex-col sm:flex-row gap-4 w-full sm:w-auto justify-center md:justify-start">
<Link
href="/create"
className="relative group overflow-hidden px-6 py-3 rounded-lg font-semibold flex items-center justify-center text-lg transition-all duration-300 focus:outline-none focus:ring-2 focus:ring-[#bf5700] focus:ring-offset-2 bg-gradient-to-r from-[#bf5700] to-[#ff9100] text-white shadow-lg border-none
before:absolute before:inset-0 before:bg-white/10 before:opacity-0 before:transition-opacity before:duration-300 group-hover:before:opacity-100
hover:scale-105 hover:-translate-y-1 hover:shadow-[0_4px_32px_0_rgba(191,87,0,0.25)]"
className="flex items-center justify-center bg-ut-orange text-white px-6 py-3 rounded-lg font-semibold text-lg transition-all duration-300 hover:scale-105 hover:-translate-y-1"
>
<FaPlus className="mr-2" />
Create Listing
<span className="absolute -bottom-1 left-1/2 -translate-x-1/2 w-2/3 h-1 bg-gradient-to-r from-[#ff9100] to-[#bf5700] rounded-full blur-sm opacity-60 group-hover:opacity-90 transition-all duration-300" />
</Link>
<Link
href="/browse"
className="relative group overflow-hidden px-6 py-3 rounded-lg font-semibold flex items-center justify-center text-lg transition-all duration-300 border-2 border-[#bf5700] bg-white text-[#bf5700] shadow-md
hover:bg-[#fff3e6] hover:text-[#a94e00] hover:border-[#ff9100] hover:scale-105 hover:-translate-y-1 focus:outline-none focus:ring-2 focus:ring-[#bf5700] focus:ring-offset-2"
className="flex items-center justify-center px-6 py-3 rounded-lg font-semibold text-lg transition-all duration-300 border-2 border-ut-orange bg-white text-ut-orange shadow-md hover:scale-105 hover:-translate-y-1"
>
<FaSearch className="mr-2" />
Browse Items
<span className="absolute -bottom-1 left-1/2 -translate-x-1/2 w-2/3 h-1 bg-gradient-to-r from-[#bf5700] to-[#ff9100] rounded-full blur-sm opacity-0 group-hover:opacity-60 transition-all duration-300" />
<FaSearch className="mr-2" /> Browse Items
</Link>
</motion.div>
</div>
{/* Right: Animated Icon */}
<motion.div
variants={itemVariants}
className="md:w-1/2 flex justify-center items-center"
Expand Down
31 changes: 21 additions & 10 deletions components/home/Recents.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ import ListingCard from "../../app/browse/components/ListingCard"
import { useEffect, useState } from "react"
import * as timeago from "timeago.js"
import { ListingService } from "../../app/lib/database/ListingService"
import { UserService } from "../../app/lib/database/UserService"
import { Listing } from "../../app/props/listing"
import { dbLogger } from "../../app/lib/database/utils"
import { supabase } from "../../app/lib/supabaseClient"
import { Clock } from "lucide-react"

const RecentListings = () => {
const [listings, setListings] = useState<Listing[]>([]);
Expand All @@ -18,7 +18,7 @@ const RecentListings = () => {
try {
setLoading(true);
const data = await ListingService.getListings({
limit: 6,
limit: 8,
excludeSold: true,
excludeDrafts: true
});
Expand Down Expand Up @@ -66,14 +66,19 @@ const RecentListings = () => {
return (
<section className="py-12 px-4 md:px-6 max-w-7xl mx-auto">
<div className="flex justify-between items-center mb-6">
<h2 className="text-2xl font-bold text-gray-900">Recent Listings</h2>
<Link href="/browse" className="text-orange-600 hover:text-orange-700 font-medium">
View All
</Link>
<div className="flex-1"></div>
<h2 className="text-3xl font-bold text-gray-900 flex items-center justify-center gap-2">
<Clock className="w-8 h-8 text-ut-orange" />
Recent Listings
</h2>
<div className="flex-1 flex justify-end">
<Link href="/browse" className="text-ut-orange hover:text-ut-orange/80 font-medium">View All</Link>
</div>
</div>

{loading ? (
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6">
{[...Array(6)].map((_, index) => (
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-6">
{[...Array(8)].map((_, index) => (
<div key={index} className="bg-white border border-gray-200 rounded-xl overflow-hidden shadow-sm animate-pulse">
<div className="aspect-[4/3] bg-gray-200" />
<div className="p-4 space-y-3">
Expand All @@ -87,7 +92,7 @@ const RecentListings = () => {
) : listings.length === 0 ? (
<div className="text-center text-gray-500 py-8">No recent listings found.</div>
) : (
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6">
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-6">
{listings.map((listing) => (
<div key={listing.id} onClick={() => window.location.href = `/listing/${listing.id}`} className="cursor-pointer">
<ListingCard
Expand All @@ -103,12 +108,18 @@ const RecentListings = () => {
image: listing.user_image
}}
condition={listing.condition}
userRating={null} // UserRatingDisplay component will fetch the rating
userRating={null}
/>
</div>
))}
</div>
)}

<div className="flex justify-center mt-8">
<div className="flex items-center justify-center bg-ut-orange text-white px-6 py-3 rounded-lg font-semibold text-lg transition-all duration-300 hover:scale-105 hover:-translate-y-1">
<Link href="/browse" className="text-white">View All</Link>
</div>
</div>
</section>
)
}
Expand Down
Binary file added public/icons/ios-light.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading