11"use client" ;
22
3- import { useState } from "react" ;
4- import { motion , type PanInfo } from "framer-motion" ;
3+ import { motion } from "framer-motion" ;
54import { BlurImage } from "@/components/ui/blur-image" ;
65import { MapPin , Coffee , Utensils , Wifi , Bus , Bike , Shield } from "lucide-react" ;
76import { GradientBlob } from "@/components/ui/GradientBlob" ;
@@ -67,18 +66,14 @@ export default function CampusLifePage() {
6766 }
6867 ] ;
6968
70- const [ currentSlide , setCurrentSlide ] = useState ( 0 ) ;
71-
72- // 288px card + 16px gap = 304px per slide
73- const getSlideOffset = ( index : number ) => - index * 304 ;
69+ const containerVariants = {
70+ hidden : { opacity : 0 } ,
71+ visible : { opacity : 1 , transition : { staggerChildren : 0.1 } } ,
72+ } ;
7473
75- const handleDragEnd = ( _ : MouseEvent | TouchEvent | PointerEvent , info : PanInfo ) => {
76- const { offset, velocity } = info ;
77- let direction = 0 ;
78- if ( offset . x < - 50 || velocity . x < - 500 ) direction = 1 ;
79- else if ( offset . x > 50 || velocity . x > 500 ) direction = - 1 ;
80- const next = Math . max ( 0 , Math . min ( currentSlide + direction , oldDorms . length - 1 ) ) ;
81- setCurrentSlide ( next ) ;
74+ const itemVariants = {
75+ hidden : { opacity : 0 , y : 20 } ,
76+ visible : { opacity : 1 , y : 0 } ,
8277 } ;
8378
8479 const galleryImages = [
@@ -264,62 +259,36 @@ export default function CampusLifePage() {
264259 ) ) }
265260 </ div >
266261
267- { /* Mobile Drag Carousel */ }
268- < div className = "md:hidden -mx-6 overflow-hidden" >
269- < motion . div
270- className = "flex gap-4 px-[calc((100vw-288px)/2)] cursor-grab active:cursor-grabbing touch-pan-y"
271- drag = "x"
272- dragConstraints = { {
273- left : getSlideOffset ( oldDorms . length - 1 ) ,
274- right : 0 ,
275- } }
276- dragElastic = { 0.15 }
277- onDragEnd = { handleDragEnd }
278- animate = { { x : getSlideOffset ( currentSlide ) } }
279- transition = { { type : "spring" , stiffness : 300 , damping : 30 } }
280- >
281- { oldDorms . map ( ( dorm , idx ) => (
282- < div
283- key = { idx }
284- className = "flex-shrink-0 w-[288px] select-none bg-white rounded-2xl overflow-hidden shadow-sm border border-border"
285- >
286- < div className = "h-44 overflow-hidden relative" >
287- < BlurImage src = { dorm . image } alt = { dorm . title } placeholder = "blur" className = "w-full h-full object-cover pointer-events-none" />
288- < div className = "absolute bottom-3 right-3 bg-black/70 backdrop-blur-md text-white px-2.5 py-0.5 rounded-full text-xs font-medium z-10" >
289- { dorm . price }
290- </ div >
291- </ div >
292- < div className = "p-4" >
293- < h3 className = "text-base font-bold mb-3 text-center" > { dorm . title } </ h3 >
294- < ul className = "space-y-1.5 px-6" >
295- { dorm . features . map ( ( feature , i ) => (
296- < li key = { i } className = "flex items-center gap-2 text-xs text-muted-foreground" >
297- < div className = "w-1.5 h-1.5 rounded-full bg-primary flex-shrink-0" />
298- { feature }
299- </ li >
300- ) ) }
301- </ ul >
262+ { /* Mobile */ }
263+ < div className = "md:hidden space-y-4" >
264+ { oldDorms . map ( ( dorm , idx ) => (
265+ < motion . div
266+ key = { idx }
267+ initial = { { opacity : 0 , y : 20 } }
268+ whileInView = { { opacity : 1 , y : 0 } }
269+ viewport = { { once : true , margin : "-100px" } }
270+ transition = { { delay : idx * 0.1 } }
271+ className = "bg-white rounded-2xl overflow-hidden shadow-sm border border-border"
272+ >
273+ < div className = "h-44 overflow-hidden relative" >
274+ < BlurImage src = { dorm . image } alt = { dorm . title } placeholder = "blur" className = "w-full h-full object-cover" />
275+ < div className = "absolute bottom-3 right-3 bg-black/70 backdrop-blur-md text-white px-2.5 py-0.5 rounded-full text-xs font-medium z-10" >
276+ { dorm . price }
302277 </ div >
303278 </ div >
304- ) ) }
305- </ motion . div >
306- { /* Dot indicators */ }
307- < div className = "flex justify-center mt-4" >
308- < div className = "flex gap-2.5 items-center" >
309- { oldDorms . map ( ( _ , index ) => (
310- < button
311- key = { index }
312- className = { `rounded-full transition-all duration-200 ${
313- currentSlide === index
314- ? "bg-primary w-3 h-3"
315- : "bg-primary/30 w-2.5 h-2.5"
316- } `}
317- onClick = { ( ) => setCurrentSlide ( index ) }
318- aria-label = { `Go to slide ${ index + 1 } ` }
319- />
320- ) ) }
321- </ div >
322- </ div >
279+ < div className = "p-4" >
280+ < h3 className = "text-base font-bold mb-3 text-center" > { dorm . title } </ h3 >
281+ < ul className = "space-y-1.5 px-6" >
282+ { dorm . features . map ( ( feature , i ) => (
283+ < li key = { i } className = "flex items-center gap-2 text-xs text-muted-foreground" >
284+ < div className = "w-1.5 h-1.5 rounded-full bg-primary flex-shrink-0" />
285+ { feature }
286+ </ li >
287+ ) ) }
288+ </ ul >
289+ </ div >
290+ </ motion . div >
291+ ) ) }
323292 </ div >
324293 </ div >
325294 </ div >
@@ -331,46 +300,51 @@ export default function CampusLifePage() {
331300 < h2 className = "text-3xl font-display font-bold mb-4" > Life at BIT</ h2 >
332301 < p className = "text-muted-foreground" > Everything you need within walking distance.</ p >
333302 </ div >
334- < div className = "flex flex-wrap gap-6" >
303+ < motion . div
304+ variants = { containerVariants }
305+ initial = "hidden"
306+ whileInView = "visible"
307+ viewport = { { once : true } }
308+ className = "grid grid-cols-2 gap-3 md:gap-8"
309+ >
335310 { facilities . map ( ( item , idx ) => (
336311 < motion . div
337312 key = { idx }
338- initial = { { opacity : 0 , scale : 0.95 } }
339- whileInView = { { opacity : 1 , scale : 1 } }
340- viewport = { { once : true , margin : "-50px" } }
341- transition = { { delay : idx * 0.05 } }
342- className = "bg-white/60 backdrop-blur-sm p-6 rounded-2xl border border-white/40 hover:bg-white/80 transition-colors w-[calc(50%-0.75rem)] md:w-[calc(33.333%-1rem)]"
313+ variants = { itemVariants }
314+ className = "bg-white/50 backdrop-blur-md border border-white/60 rounded-2xl md:rounded-3xl p-4 md:p-8 hover:shadow-xl transition-all duration-300 group"
343315 >
344- < item . icon className = "w-8 h-8 text-primary mb-4" />
345- < h3 className = "font-bold text-lg mb-2" > { item . title } </ h3 >
346- < p className = "text-sm text-muted-foreground leading-relaxed" > { item . desc } </ p >
316+ < div className = "w-9 h-9 md:w-12 md:h-12 bg-primary/10 rounded-xl md:rounded-2xl flex items-center justify-center mb-3 md:mb-6 group-hover:scale-110 transition-transform" >
317+ < item . icon className = "w-4 h-4 md:w-6 md:h-6 text-primary" />
318+ </ div >
319+ < h3 className = "text-sm md:text-2xl font-bold font-display mb-1.5 md:mb-3" > { item . title } </ h3 >
320+ < p className = "text-xs md:text-base text-muted-foreground leading-relaxed" > { item . desc } </ p >
347321 </ motion . div >
348322 ) ) }
349- </ div >
323+ </ motion . div >
350324 </ div >
351325
352326 { /* Gallery */ }
353- < div >
327+ < div className = "mb-32" >
354328 < h2 className = "text-3xl font-display font-bold mb-12 text-center" > Campus Moments</ h2 >
355- < div className = "mb-24 flex flex-wrap gap-4 md:gap-6" >
356- { galleryImages . map ( ( img , idx ) => (
329+ < div className = "columns-2 md:columns-3 gap-4 md:gap-6" >
330+ { galleryImages . map ( ( item , idx ) => (
357331 < motion . div
358332 key = { idx }
359333 initial = { { opacity : 0 , scale : 0.9 } }
360334 whileInView = { { opacity : 1 , scale : 1 } }
361335 viewport = { { once : true , margin : "-50px" } }
362336 transition = { { delay : idx * 0.1 } }
363- className = "relative rounded-2xl overflow-hidden group w-[calc(50%-0.5rem)] md:w-[calc(33.333%-1rem)] "
337+ className = "relative rounded-2xl overflow-hidden group break-inside-avoid mb-6 "
364338 >
365339 < div className = "absolute inset-0 bg-gradient-to-t from-black/60 via-transparent to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-300 z-10" />
366340 < BlurImage
367- src = { img . src }
368- alt = { img . caption }
341+ src = { item . src }
342+ alt = { item . caption }
369343 className = "w-full h-auto object-cover transform group-hover:scale-105 transition-transform duration-700"
370344 sizes = "(max-width: 768px) 100vw, 33vw"
371345 />
372346 < div className = "absolute bottom-0 left-0 right-0 p-6 translate-y-full group-hover:translate-y-0 transition-transform duration-300 z-20" >
373- < p className = "text-white font-medium text-sm" > { img . caption } </ p >
347+ < p className = "text-white font-medium text-sm" > { item . caption } </ p >
374348 </ div >
375349 </ motion . div >
376350 ) ) }
0 commit comments