Merge pull request #2 from Annisanzn/nisa2

Nisa2
This commit is contained in:
Annisa Nurul Hidayatil Jannah 2026-02-17 18:16:30 +07:00 committed by GitHub
commit 2cbabf0554
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 242 additions and 411 deletions

View File

@ -1,11 +1,13 @@
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
import { motion } from 'framer-motion'; import { motion } from 'framer-motion';
import { MapPin, Phone, Mail, Instagram, MessageCircle, Globe, Clock, ShieldAlert } from 'lucide-react';
import { fadeIn, slideUp, staggerChildren } from '../utils/motionVariants'; import { fadeIn, slideUp, staggerChildren } from '../utils/motionVariants';
import { SpotlightCard } from './ui/spotlight-card';
import { FlowButton } from './ui/flow-button';
const Contact = () => { const Contact = () => {
const [contactInfo, setContactInfo] = useState(null); const [contactInfo, setContactInfo] = useState(null);
const [loading, setLoading] = useState(true); const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => { useEffect(() => {
// Temporary disable API calls to prevent 404 errors // Temporary disable API calls to prevent 404 errors
@ -18,7 +20,7 @@ const Contact = () => {
facebook: 'SatgasPPKPTPolije', facebook: 'SatgasPPKPTPolije',
twitter: '@SatgasPPKPTPolije' twitter: '@SatgasPPKPTPolije'
}; };
setContactInfo(mockContactInfo); setContactInfo(mockContactInfo);
setLoading(false); setLoading(false);
}, []); }, []);
@ -35,250 +37,181 @@ const Contact = () => {
const contactMethods = [ const contactMethods = [
{ {
icon: ( icon: <Phone className="w-6 h-6" />,
<svg className="w-8 h-8" fill="currentColor" viewBox="0 0 24 24"> label: 'Telepon Kantor',
<path d="M6.62 10.79c1.44 2.83 3.76 5.14 6.59 6.59l2.2-2.2c.27-.27.67-.36 1.02-.24 1.12.37 2.33.57 3.57.57.55 0 1 .45 1 1V20c0 .55-.45 1-1 1-9.39 0-17-7.61-17-17 0-.55.45-1 1-1h3.5c.55 0 1 .45 1 1 0 1.25.2 2.45.57 3.57.11.35.03.74-.25 1.02l-2.2 2.2z"/>
</svg>
),
label: 'Telepon',
value: contact.phone, value: contact.phone,
href: `tel:${contact.phone}`, href: `tel:${contact.phone}`,
color: 'text-primary' color: 'text-blue-500',
spotlight: 'rgba(59, 130, 246, 0.2)'
}, },
{ {
icon: ( icon: <Mail className="w-6 h-6" />,
<svg className="w-8 h-8" fill="currentColor" viewBox="0 0 24 24"> label: 'Email Resmi',
<path d="M20 4H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm0 4l-8 5-8-5V6l8 5 8-5v2z"/>
</svg>
),
label: 'Email',
value: contact.email, value: contact.email,
href: `mailto:${contact.email}`, href: `mailto:${contact.email}`,
color: 'text-primary' color: 'text-purple-500',
spotlight: 'rgba(168, 85, 247, 0.2)'
}, },
{ {
icon: ( icon: <Instagram className="w-6 h-6" />,
<svg className="w-8 h-8" fill="currentColor" viewBox="0 0 24 24"> label: 'Instagram',
<path d="M17.472 14.382c-.297-.149-1.758-.867-2.03-.967-.273-.099-.471-.149-.67.149-.197.297-.767.966-.94 1.164-.173.199-.347.223-.644.074-.297-.149-1.255-.462-2.39-1.475-.883-.788-1.48-1.761-1.653-2.059-.173-.297-.018-.458.13-.606.134-.133.297-.347.446-.521.151-.172.2-.296.3-.495.099-.198.05-.372-.025-.521-.075-.148-.669-1.611-.916-2.206-.242-.579-.487-.501-.669-.51l-.57-.01c-.198 0-.52.074-.792.372s-1.04 1.016-1.04 2.479 1.065 2.876 1.213 3.074c.149.198 2.095 3.2 5.076 4.487.709.306 1.263.489 1.694.626.712.226 1.36.194 1.872.118.571-.085 1.758-.719 2.006-1.413.248-.695.248-1.29.173-1.414-.074-.123-.272-.198-.57-.347m-5.421 7.403h-.004a9.87 9.87 0 01-5.031-1.378l-.361-.214-3.741.982.998-3.648-.235-.374a9.86 9.86 0 01-1.51-5.26c.001-5.45 4.436-9.884 9.888-9.884 2.64 0 5.122 1.03 6.988 2.898a9.825 9.825 0 012.893 6.994c-.003 5.45-4.437 9.884-9.885 9.884m8.413-18.297A11.815 11.815 0 0012.05 0C5.495 0 .16 5.335.157 11.892c0 2.096.547 4.142 1.588 5.945L.057 24l6.305-1.654a11.882 11.882 0 005.683 1.448h.005c6.554 0 11.89-5.335 11.893-11.893a11.821 11.821 0 00-3.48-8.413"/> value: contact.instagram,
</svg> href: `https://instagram.com/${contact.instagram?.replace('@', '')}`,
), color: 'text-pink-500',
label: 'WhatsApp', spotlight: 'rgba(236, 72, 153, 0.2)'
},
{
icon: <MessageCircle className="w-6 h-6" />,
label: 'WhatsApp Admin',
value: contact.whatsapp, value: contact.whatsapp,
href: `https://wa.me/${contact.whatsapp?.replace(/[^0-9]/g, '')}`, href: `https://wa.me/${contact.whatsapp?.replace(/[^0-9]/g, '')}`,
color: 'text-accent' color: 'text-green-500',
} spotlight: 'rgba(34, 197, 94, 0.2)'
];
const socialMedia = [
{
name: 'Instagram',
icon: (
<svg className="w-6 h-6" fill="currentColor" viewBox="0 0 24 24">
<path d="M12 2.163c3.204 0 3.584.012 4.85.07 3.252.148 4.771 1.691 4.919 4.919.058 1.265.069 1.645.069 4.849 0 3.205-.012 3.584-.069 4.849-.149 3.225-1.664 4.771-4.919 4.919-1.266.058-1.644.07-4.85.07-3.204 0-3.584-.012-4.849-.07-3.26-.149-4.771-1.699-4.919-4.92-.058-1.265-.07-1.644-.07-4.849 0-3.204.013-3.583.07-4.849.149-3.227 1.664-4.771 4.919-4.919 1.266-.057 1.645-.069 4.849-.069zm0-2.163c-3.259 0-3.667.014-4.947.072-4.358.2-6.78 2.618-6.98 6.98-.059 1.281-.073 1.689-.073 4.948 0 3.259.014 3.668.072 4.948.2 4.358 2.618 6.78 6.98 6.98 1.281.058 1.689.072 4.948.072 3.259 0 3.668-.014 4.948-.072 4.354-.2 6.782-2.618 6.979-6.98.059-1.28.073-1.689.073-4.948 0-3.259-.014-3.667-.072-4.947-.196-4.354-2.617-6.78-6.979-6.98-1.281-.059-1.69-.073-4.949-.073zM5.838 12a6.162 6.162 0 1112.324 0 6.162 6.162 0 01-12.324 0zM12 16a4 4 0 110-8 4 4 0 010 8zm4.965-10.405a1.44 1.44 0 112.881.001 1.44 1.44 0 01-2.881-.001z"/>
</svg>
),
href: `https://instagram.com/${contact.instagram?.replace('@', '')}`,
color: 'hover:text-pink-600'
} }
]; ];
return ( return (
<section id="contact" className="py-20 bg-gray-50 relative overflow-hidden"> <section id="contact" className="py-24 bg-gray-50 dark:bg-gray-900 relative overflow-hidden">
{/* Background Pattern */} {/* Background Decorations */}
<div className="absolute inset-0 opacity-5"> <div className="absolute top-0 left-0 w-full h-full overflow-hidden pointer-events-none">
<div className="absolute top-20 right-20 w-72 h-72 bg-primary rounded-full blur-3xl"></div> <div className="absolute top-[10%] left-[5%] w-[500px] h-[500px] bg-primary/5 rounded-full blur-3xl"></div>
<div className="absolute bottom-20 left-20 w-96 h-96 bg-accent rounded-full blur-3xl"></div> <div className="absolute bottom-[10%] right-[5%] w-[500px] h-[500px] bg-blue-500/5 rounded-full blur-3xl"></div>
</div> </div>
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 relative z-10"> <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 relative z-10">
{/* Section Header */} {/* Section Header */}
<motion.div <motion.div
className="text-center mb-20" className="text-center mb-16"
variants={fadeIn} variants={fadeIn}
initial="hidden" initial="hidden"
whileInView="visible" whileInView="visible"
viewport={{ once: true }} viewport={{ once: true }}
> >
<motion.h2 <motion.h2
className="text-4xl md:text-5xl font-bold text-gray-900 mb-6" className="text-4xl md:text-5xl font-bold text-gray-900 dark:text-white mb-6"
variants={slideUp} variants={slideUp}
initial="hidden"
whileInView="visible"
viewport={{ once: true }}
> >
Hubungi <span className="text-primary">Kami</span> Hubungi <span className="text-primary">Kami</span>
</motion.h2> </motion.h2>
<motion.p <p className="text-xl text-gray-600 dark:text-gray-300 max-w-3xl mx-auto leading-relaxed">
className="text-xl text-gray-600 max-w-3xl mx-auto leading-relaxed" Kami siap membantu Anda. Jangan ragu untuk menghubungi kami melalui berbagai saluran komunikasi yang tersedia. Privasi Anda adalah prioritas kami.
variants={fadeIn} </p>
initial="hidden"
whileInView="visible"
viewport={{ once: true }}
transition={{ delay: 0.2 }}
>
Kami siap membantu Anda. Jangan ragu untuk menghubungi kami melalui berbagai metode komunikasi yang tersedia.
</motion.p>
</motion.div> </motion.div>
{/* Loading State */}
{loading && (
<motion.div
className="flex justify-center items-center py-20"
variants={fadeIn}
initial="hidden"
animate="visible"
>
<div className="flex flex-col items-center space-y-4">
<div className="w-12 h-12 border-4 border-primary/20 border-t-primary rounded-full animate-spin"></div>
<p className="text-gray-600 font-medium">Memuat informasi kontak...</p>
</div>
</motion.div>
)}
{/* Contact Content */}
{!loading && ( {!loading && (
<div className="grid grid-cols-1 lg:grid-cols-2 gap-12"> <div className="grid grid-cols-1 lg:grid-cols-12 gap-8">
{/* Contact Information */} {/* Left Column: Contact Info & Emergency */}
<motion.div <div className="lg:col-span-5 space-y-8">
variants={fadeIn}
initial="hidden" {/* Emergency Card */}
whileInView="visible" <SpotlightCard
viewport={{ once: true }} className="rounded-3xl p-8 border border-red-200/50 bg-red-50/50 dark:bg-red-900/20 dark:border-red-500/30 backdrop-blur-sm"
> spotlightColor="rgba(239, 68, 68, 0.15)"
<div className="bg-white rounded-3xl p-8 shadow-soft"> >
<h3 className="text-2xl font-bold text-gray-900 mb-8">Informasi Kontak</h3> <div className="flex items-start space-x-4">
<div className="w-12 h-12 bg-red-100 dark:bg-red-900/50 rounded-xl flex items-center justify-center flex-shrink-0 text-red-600 dark:text-red-400">
{/* Contact Methods */} <ShieldAlert className="w-7 h-7" />
<div className="space-y-6 mb-8"> </div>
{contactMethods.map((method, index) => ( <div>
<motion.div <h3 className="text-xl font-bold text-gray-900 dark:text-white mb-2">Bantuan Darurat 24/7</h3>
key={index} <p className="text-gray-600 dark:text-gray-300 mb-6 text-sm">
className="flex items-start space-x-4 p-4 rounded-xl hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors" Jika Anda dalam situasi darurat atau bahaya, segera hubungi tim Satgas PPKS melalui saluran khusus ini.
variants={fadeIn} </p>
initial="hidden" <FlowButton
whileInView="visible" text="Hubungi Darurat Sekarang"
viewport={{ once: true }} href={`https://wa.me/${contact.whatsapp?.replace(/[^0-9]/g, '')}`}
transition={{ delay: 0.1 * index }} target="_blank"
colorStr="#ef4444"
hoverColorStr="#dc2626"
className="w-full"
/>
</div>
</div>
</SpotlightCard>
{/* General Contact Info */}
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
{contactMethods.map((method, index) => (
<SpotlightCard
key={index}
className="rounded-2xl p-6 border border-white/20 bg-white/60 dark:bg-black/20 dark:border-white/10 backdrop-blur-md shadow-sm hover:shadow-md transition-all group"
spotlightColor={method.spotlight}
>
<a
href={method.href}
target={method.href.startsWith('http') ? '_blank' : '_self'}
rel={method.href.startsWith('http') ? 'noopener noreferrer' : undefined}
className="flex flex-col items-center text-center h-full"
> >
<div className={`w-12 h-12 bg-gradient-to-br from-primary/10 to-accent/10 dark:from-primary/20 dark:to-accent/20 rounded-xl flex items-center justify-center ${method.color} flex-shrink-0`}> <div className={`w-12 h-12 rounded-full bg-gray-50 dark:bg-white/5 flex items-center justify-center mb-4 ${method.color} group-hover:scale-110 transition-transform duration-300`}>
<div className={method.color === 'text-primary' ? 'text-primary dark:text-primary-light' : method.color === 'text-accent' ? 'text-accent dark:text-accent-light' : 'text-gray-700 dark:text-gray-300'}> {method.icon}
{method.icon}
</div>
</div> </div>
<div className="flex-1"> <h4 className="font-semibold text-gray-900 dark:text-white mb-1">{method.label}</h4>
<h4 className="font-semibold text-gray-900 dark:text-white mb-1">{method.label}</h4> <p className="text-sm text-gray-500 dark:text-gray-400 break-all">{method.value}</p>
<a </a>
href={method.href} </SpotlightCard>
className="text-gray-600 dark:text-gray-300 hover:text-primary dark:hover:text-primary-light transition-colors" ))}
target={method.href.startsWith('http') ? '_blank' : '_self'} </div>
rel={method.href.startsWith('http') ? 'noopener noreferrer' : undefined}
{/* Operating Hours */}
<div className="bg-white/60 dark:bg-black/20 border border-white/20 dark:border-white/10 rounded-2xl p-6 backdrop-blur-sm">
<div className="flex items-center space-x-3 mb-4">
<Clock className="w-5 h-5 text-primary" />
<h4 className="font-semibold text-gray-900 dark:text-white">Jam Operasional Kantor</h4>
</div>
<ul className="space-y-2 text-sm text-gray-600 dark:text-gray-300">
<li className="flex justify-between">
<span>Senin - Jumat</span>
<span className="font-medium">08.00 - 16.00 WIB</span>
</li>
<li className="flex justify-between">
<span>Sabtu - Minggu</span>
<span className="font-medium text-red-500">Tutup (Kecuali Darurat)</span>
</li>
</ul>
</div>
</div>
{/* Right Column: Map */}
<div className="lg:col-span-7 h-full min-h-[500px]">
<SpotlightCard
className="h-full rounded-3xl p-2 border border-white/20 bg-white/60 dark:bg-black/20 dark:border-white/10 backdrop-blur-md shadow-xl overflow-hidden"
spotlightColor="rgba(255, 255, 255, 0.1)"
>
<div className="relative w-full h-full rounded-2xl overflow-hidden group">
<iframe
title="Lokasi Politeknik Negeri Jember"
src="https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d3949.424564483758!2d113.72093787447761!3d-8.16021369187063!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x2dd695b617d8f623%3A0x280e466373737b60!2sPoliteknik%20Negeri%20Jember!5e0!3m2!1sid!2sid!4v1708150000000!5m2!1sid!2sid"
width="100%"
height="100%"
style={{ border: 0, minHeight: '500px' }}
allowFullScreen=""
loading="lazy"
referrerPolicy="no-referrer-when-downgrade"
className="grayscale hover:grayscale-0 transition-all duration-700 ease-in-out"
></iframe>
{/* Map Overlay Info */}
<div className="absolute bottom-6 left-6 right-6 bg-white/90 dark:bg-black/80 backdrop-blur-md p-4 rounded-xl border border-white/20 shadow-lg translate-y-full opacity-0 group-hover:translate-y-0 group-hover:opacity-100 transition-all duration-500">
<div className="flex items-start space-x-3">
<MapPin className="w-5 h-5 text-red-500 flex-shrink-0 mt-1" />
<div>
<h5 className="font-bold text-gray-900 dark:text-white">Kampus Politeknik Negeri Jember</h5>
<p className="text-sm text-gray-600 dark:text-gray-300 mt-1">{contact.address}</p>
<a
href="https://maps.app.goo.gl/politekniknegerijember"
target="_blank"
rel="noopener noreferrer"
className="inline-block mt-2 text-xs font-semibold text-primary hover:underline"
> >
{method.value} Buka di Google Maps
</a> </a>
</div> </div>
</motion.div>
))}
</div>
{/* Address */}
<div className="p-4 bg-gray-50 rounded-xl">
<div className="flex items-start space-x-4">
<div className="w-12 h-12 bg-gradient-to-br from-primary/10 to-accent/10 rounded-xl flex items-center justify-center text-primary flex-shrink-0">
<svg className="w-6 h-6" fill="currentColor" viewBox="0 0 24 24">
<path d="M12 2C8.13 2 5 5.13 5 9c0 5.25 7 13 7 13s7-7.75 7-13c0-3.87-3.13-7-7-7zm0 9.5c-1.38 0-2.5-1.12-2.5-2.5s1.12-2.5 2.5-2.5 2.5 1.12 2.5 2.5-1.12 2.5-2.5 2.5z"/>
</svg>
</div>
<div>
<h4 className="font-semibold text-gray-900 mb-1">Alamat</h4>
<p className="text-gray-600 leading-relaxed">{contact.address}</p>
</div> </div>
</div> </div>
</div> </div>
</SpotlightCard>
{/* Social Media */} </div>
<div className="mt-8 pt-8 border-t border-gray-200">
<h4 className="font-semibold text-gray-900 mb-4">Ikuti Kami</h4>
<div className="flex space-x-4">
{socialMedia.map((social, index) => (
<motion.a
key={index}
href={social.href}
target="_blank"
rel="noopener noreferrer"
className={`w-12 h-12 bg-gray-100 rounded-xl flex items-center justify-center text-gray-600 ${social.color} transition-all duration-300`}
variants={fadeIn}
initial="hidden"
whileInView="visible"
viewport={{ once: true }}
transition={{ delay: 0.2 * index }}
whileHover={{ scale: 1.1 }}
>
{social.icon}
</motion.a>
))}
</div>
</div>
</div>
</motion.div>
{/* Emergency Contact */}
<motion.div
variants={fadeIn}
initial="hidden"
whileInView="visible"
viewport={{ once: true }}
transition={{ delay: 0.2 }}
>
<div className="bg-gradient-to-br from-danger/10 to-danger/5 border border-danger/20 rounded-3xl p-8">
<div className="text-center mb-8">
<div className="w-16 h-16 bg-danger/20 rounded-2xl flex items-center justify-center mx-auto mb-4">
<svg className="w-8 h-8 text-danger" fill="currentColor" viewBox="0 0 24 24">
<path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z"/>
</svg>
</div>
<h3 className="text-2xl font-bold text-gray-900 mb-4">Butuh Bantuan Darurat?</h3>
<p className="text-gray-600 leading-relaxed">
Jika Anda atau orang lain berada dalam situasi darurat, segera hubungi kami untuk respons cepat 24/7.
</p>
</div>
<div className="space-y-4">
<motion.a
href={`https://wa.me/${contact.whatsapp?.replace(/[^0-9]/g, '')}`}
target="_blank"
rel="noopener noreferrer"
className="flex items-center justify-center w-full px-6 py-4 bg-danger text-white rounded-xl hover:bg-danger-dark transition-all duration-300 font-semibold shadow-soft hover:shadow-lg"
variants={fadeIn}
initial="hidden"
whileInView="visible"
viewport={{ once: true }}
transition={{ delay: 0.3 }}
whileHover={{ scale: 1.02 }}
>
<svg className="w-5 h-5 mr-2" fill="currentColor" viewBox="0 0 24 24">
<path d="M17.472 14.382c-.297-.149-1.758-.867-2.03-.967-.273-.099-.471-.149-.67.149-.197.297-.767.966-.94 1.164-.173.199-.347.223-.644.074-.297-.149-1.255-.462-2.39-1.475-.883-.788-1.48-1.761-1.653-2.059-.173-.297-.018-.458.13-.606.134-.133.297-.347.446-.521.151-.172.2-.296.3-.495.099-.198.05-.372-.025-.521-.075-.148-.669-1.611-.916-2.206-.242-.579-.487-.501-.669-.51l-.57-.01c-.198 0-.52.074-.792.372s-1.04 1.016-1.04 2.479 1.065 2.876 1.213 3.074c.149.198 2.095 3.2 5.076 4.487.709.306 1.263.489 1.694.626.712.226 1.36.194 1.872.118.571-.085 1.758-.719 2.006-1.413.248-.695.248-1.29.173-1.414-.074-.123-.272-.198-.57-.347m-5.421 7.403h-.004a9.87 9.87 0 01-5.031-1.378l-.361-.214-3.741.982.998-3.648-.235-.374a9.86 9.86 0 01-1.51-5.26c.001-5.45 4.436-9.884 9.888-9.884 2.64 0 5.122 1.03 6.988 2.898a9.825 9.825 0 012.893 6.994c-.003 5.45-4.437 9.884-9.885 9.884m8.413-18.297A11.815 11.815 0 0012.05 0C5.495 0 .16 5.335.157 11.892c0 2.096.547 4.142 1.588 5.945L.057 24l6.305-1.654a11.882 11.882 0 005.683 1.448h.005c6.554 0 11.89-5.335 11.893-11.893a11.821 11.821 0 00-3.48-8.413"/>
</svg>
Hubungi WhatsApp Darurat
</motion.a>
<motion.div
className="text-center p-4 bg-white/80 rounded-xl"
variants={fadeIn}
initial="hidden"
whileInView="visible"
viewport={{ once: true }}
transition={{ delay: 0.4 }}
>
<div className="flex items-center justify-center space-x-2 text-gray-600">
<svg className="w-5 h-5 text-accent" fill="currentColor" viewBox="0 0 24 24">
<path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z"/>
</svg>
<span className="font-medium">Respons 24/7 - Privasi Terjamin</span>
</div>
</motion.div>
</div>
</div>
</motion.div>
</div> </div>
)} )}
</div> </div>

View File

@ -1,237 +1,135 @@
import React from 'react'; import React from 'react';
import { motion } from 'framer-motion'; import { motion } from 'framer-motion';
import { fadeIn } from '../utils/motionVariants'; import { Facebook, Instagram, Twitter, Linkedin, Heart, Shield, Mail, Phone, MapPin } from 'lucide-react';
const Footer = () => { const Footer = () => {
const currentYear = new Date().getFullYear(); const currentYear = new Date().getFullYear();
const quickLinks = [ const footerLinks = {
{ name: 'Beranda', href: '#hero' }, 'Menu Utama': [
{ name: 'Tentang Kami', href: '#about' }, { name: 'Beranda', href: '#hero' },
{ name: 'Layanan', href: '#services' }, { name: 'Tentang Kami', href: '#about' },
{ name: 'Artikel', href: '/artikel' }, { name: 'Layanan', href: '#services' },
{ name: 'Kontak', href: '#contact' } { name: 'Artikel', href: '/artikel' },
]; ],
'Layanan': [
const services = [ { name: 'Pelaporan Online', href: '#services' },
{ name: 'WhatsApp Reporting', href: 'https://wa.me/6281234567890' }, { name: 'Konsultasi Psikologi', href: '#contact' },
{ name: 'Form Reporting', href: '/artikel' }, { name: 'Pendampingan Hukum', href: '#contact' },
{ name: 'Konsultasi', href: '#contact' }, { name: 'Edukasi & Sosialisasi', href: '/artikel' },
{ name: 'Pendampingan', href: '#contact' } ],
]; 'Bantuan': [
{ name: 'Kontak Darurat', href: '#contact' },
{ name: 'Prosedur Lapor', href: '#services' },
{ name: 'FAQ', href: '#faq' },
{ name: 'Kebijakan Privasi', href: '#' },
]
};
const socialLinks = [ const socialLinks = [
{ { icon: <Instagram className="w-5 h-5" />, href: 'https://instagram.com/satgasppkpt_polije', label: 'Instagram' },
name: 'Instagram', { icon: <Twitter className="w-5 h-5" />, href: '#', label: 'Twitter' },
icon: ( { icon: <Facebook className="w-5 h-5" />, href: '#', label: 'Facebook' },
<svg className="w-5 h-5" fill="currentColor" viewBox="0 0 24 24"> { icon: <Linkedin className="w-5 h-5" />, href: '#', label: 'LinkedIn' },
<path d="M12 2.163c3.204 0 3.584.012 4.85.07 3.252.148 4.771 1.691 4.919 4.919.058 1.265.069 1.645.069 4.849 0 3.205-.012 3.584-.069 4.849-.149 3.225-1.664 4.771-4.919 4.919-1.266.058-1.644.07-4.85.07-3.204 0-3.584-.012-4.849-.07-3.26-.149-4.771-1.699-4.919-4.92-.058-1.265-.07-1.644-.07-4.849 0-3.204.013-3.583.07-4.849.149-3.227 1.664-4.771 4.919-4.919 1.266-.057 1.645-.069 4.849-.069zm0-2.163c-3.259 0-3.667.014-4.947.072-4.358.2-6.78 2.618-6.98 6.98-.059 1.281-.073 1.689-.073 4.948 0 3.259.014 3.668.072 4.948.2 4.358 2.618 6.78 6.98 6.98 1.281.058 1.689.072 4.948.072 3.259 0 3.668-.014 4.948-.072 4.354-.2 6.782-2.618 6.979-6.98.059-1.28.073-1.689.073-4.948 0-3.259-.014-3.667-.072-4.947-.196-4.354-2.617-6.78-6.979-6.98-1.281-.059-1.69-.073-4.949-.073zM5.838 12a6.162 6.162 0 1112.324 0 6.162 6.162 0 01-12.324 0zM12 16a4 4 0 110-8 4 4 0 010 8zm4.965-10.405a1.44 1.44 0 112.881.001 1.44 1.44 0 01-2.881-.001z"/>
</svg>
),
href: 'https://instagram.com/satgasppkpt_polije'
}
]; ];
return ( return (
<footer className="bg-gray-900 text-white relative overflow-hidden"> <footer className="bg-white/80 dark:bg-black/80 backdrop-blur-md border-t border-gray-200/50 dark:border-white/5 pt-20 pb-10 relative overflow-hidden">
{/* Background Pattern */} {/* Background Gradients */}
<div className="absolute inset-0 opacity-5"> <div className="absolute inset-0 bg-[radial-gradient(circle_at_top_right,_var(--tw-gradient-stops))] from-primary/5 via-transparent to-transparent opacity-70"></div>
<div className="absolute top-10 right-10 w-64 h-64 bg-primary rounded-full blur-3xl"></div> <div className="absolute inset-0 bg-[radial-gradient(circle_at_bottom_left,_var(--tw-gradient-stops))] from-blue-500/5 via-transparent to-transparent opacity-70"></div>
<div className="absolute bottom-10 left-10 w-96 h-96 bg-accent rounded-full blur-3xl"></div>
</div>
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 relative z-10"> <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 relative z-10">
{/* Main Footer Content */} <div className="grid grid-cols-1 lg:grid-cols-12 gap-12 lg:gap-8 mb-16">
<div className="py-16"> {/* Brand Column */}
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-12"> <div className="lg:col-span-4 space-y-6">
{/* Logo and Description */} <motion.div
<motion.div initial={{ opacity: 0, y: 20 }}
className="space-y-6" whileInView={{ opacity: 1, y: 0 }}
variants={fadeIn}
initial="hidden"
whileInView="visible"
viewport={{ once: true }} viewport={{ once: true }}
className="flex items-center gap-4"
> >
<div className="flex items-center space-x-3"> <img
<div className="relative"> src="/logo_polijecare.png"
<div className="w-12 h-12 bg-gradient-to-br from-primary to-accent rounded-full flex items-center justify-center shadow-lg"> alt="PolijeCare Logo"
<div className="w-7 h-7 bg-white rounded-full flex items-center justify-center"> className="w-14 h-14 object-contain filter drop-shadow-sm"
<div className="w-4 h-4 bg-gradient-to-br from-primary to-accent rounded-full"></div> />
</div> <div className="space-y-0.5">
</div> <h3 className="text-2xl font-bold tracking-tight text-gray-900 dark:text-white">
<div className="absolute -top-1 -right-1 w-4 h-4 bg-accent rounded-full animate-pulse"></div> PolijeCare
</div> </h3>
<span className="text-2xl font-bold text-white">PolijeCare</span> <p className="text-[10px] uppercase tracking-[0.2em] font-semibold text-primary">
</div> Satgas PPKS Polije
<p className="text-gray-300 leading-relaxed"> </p>
Satgas PPKPT Politeknik Negeri Jember - Layanan pengaduan dan pendampingan terpercaya bagi sivitas akademika.
</p>
{/* Social Links */}
<div className="flex space-x-4">
{socialLinks.map((social, index) => (
<motion.a
key={index}
href={social.href}
target="_blank"
rel="noopener noreferrer"
className="w-10 h-10 bg-gray-800 rounded-xl flex items-center justify-center text-gray-400 hover:text-accent transition-all duration-300"
variants={fadeIn}
initial="hidden"
whileInView="visible"
viewport={{ once: true }}
transition={{ delay: 0.1 * index }}
whileHover={{ scale: 1.1, y: -2 }}
>
{social.icon}
</motion.a>
))}
</div> </div>
</motion.div> </motion.div>
{/* Quick Links */} <p className="text-gray-500 dark:text-gray-400 leading-relaxed max-w-sm text-sm">
<motion.div Mewujudkan lingkungan kampus yang aman, inklusif, dan bebas kekerasan seksual. Kami hadir untuk melayani, melindungi, dan mendampingi sivitas akademika Polije.
className="space-y-6" </p>
variants={fadeIn}
initial="hidden"
whileInView="visible"
viewport={{ once: true }}
transition={{ delay: 0.1 }}
>
<h3 className="text-lg font-bold text-white">Quick Links</h3>
<ul className="space-y-3">
{quickLinks.map((link, index) => (
<motion.li
key={index}
variants={fadeIn}
initial="hidden"
whileInView="visible"
viewport={{ once: true }}
transition={{ delay: 0.1 * index }}
>
<a
href={link.href}
className="text-gray-300 hover:text-accent transition-colors duration-300 flex items-center group"
>
<svg className="w-4 h-4 mr-2 transform group-hover:translate-x-1 transition-transform" fill="currentColor" viewBox="0 0 24 24">
<path d="M8.59 16.59L13.17 12 8.59 7.41 10 6l6 6-6 6-1.41-1.41z"/>
</svg>
{link.name}
</a>
</motion.li>
))}
</ul>
</motion.div>
{/* Services */} <div className="flex gap-3">
<motion.div {socialLinks.map((social, index) => (
className="space-y-6"
variants={fadeIn}
initial="hidden"
whileInView="visible"
viewport={{ once: true }}
transition={{ delay: 0.2 }}
>
<h3 className="text-lg font-bold text-white">Layanan</h3>
<ul className="space-y-3">
{services.map((service, index) => (
<motion.li
key={index}
variants={fadeIn}
initial="hidden"
whileInView="visible"
viewport={{ once: true }}
transition={{ delay: 0.1 * index }}
>
<a
href={service.href}
className="text-gray-300 hover:text-accent transition-colors duration-300 flex items-center group"
target={service.href.startsWith('http') ? '_blank' : '_self'}
rel={service.href.startsWith('http') ? 'noopener noreferrer' : undefined}
>
<svg className="w-4 h-4 mr-2 transform group-hover:translate-x-1 transition-transform" fill="currentColor" viewBox="0 0 24 24">
<path d="M8.59 16.59L13.17 12 8.59 7.41 10 6l6 6-6 6-1.41-1.41z"/>
</svg>
{service.name}
</a>
</motion.li>
))}
</ul>
</motion.div>
{/* Contact Info */}
<motion.div
className="space-y-6"
variants={fadeIn}
initial="hidden"
whileInView="visible"
viewport={{ once: true }}
transition={{ delay: 0.3 }}
>
<h3 className="text-lg font-bold text-white">Kontak Darurat</h3>
<div className="space-y-4">
<motion.a <motion.a
href="https://wa.me/6281234567890" key={index}
href={social.href}
target="_blank" target="_blank"
rel="noopener noreferrer" rel="noopener noreferrer"
className="flex items-center space-x-3 text-gray-300 hover:text-accent transition-colors" aria-label={social.label}
variants={fadeIn} className="w-9 h-9 flex items-center justify-center rounded-full bg-gray-100 dark:bg-white/5 text-gray-500 dark:text-gray-400 hover:bg-primary hover:text-white dark:hover:bg-primary dark:hover:text-white transition-all duration-300"
initial="hidden" whileHover={{ scale: 1.05 }}
whileInView="visible" whileTap={{ scale: 0.95 }}
viewport={{ once: true }}
whileHover={{ x: 4 }}
> >
<div className="w-10 h-10 bg-green-500/20 rounded-lg flex items-center justify-center"> {React.cloneElement(social.icon, { className: "w-4 h-4" })}
<svg className="w-5 h-5 text-green-400" fill="currentColor" viewBox="0 0 24 24">
<path d="M17.472 14.382c-.297-.149-1.758-.867-2.03-.967-.273-.099-.471-.149-.67.149-.197.297-.767.966-.94 1.164-.173.199-.347.223-.644.074-.297-.149-1.255-.462-2.39-1.475-.883-.788-1.48-1.761-1.653-2.059-.173-.297-.018-.458.13-.606.134-.133.297-.347.446-.521.151-.172.2-.296.3-.495.099-.198.05-.372-.025-.521-.075-.148-.669-1.611-.916-2.206-.242-.579-.487-.501-.669-.51l-.57-.01c-.198 0-.52.074-.792.372s-1.04 1.016-1.04 2.479 1.065 2.876 1.213 3.074c.149.198 2.095 3.2 5.076 4.487.709.306 1.263.489 1.694.626.712.226 1.36.194 1.872.118.571-.085 1.758-.719 2.006-1.413.248-.695.248-1.29.173-1.414-.074-.123-.272-.198-.57-.347m-5.421 7.403h-.004a9.87 9.87 0 01-5.031-1.378l-.361-.214-3.741.982.998-3.648-.235-.374a9.86 9.86 0 01-1.51-5.26c.001-5.45 4.436-9.884 9.888-9.884 2.64 0 5.122 1.03 6.988 2.898a9.825 9.825 0 012.893 6.994c-.003 5.45-4.437 9.884-9.885 9.884m8.413-18.297A11.815 11.815 0 0012.05 0C5.495 0 .16 5.335.157 11.892c0 2.096.547 4.142 1.588 5.945L.057 24l6.305-1.654a11.882 11.882 0 005.683 1.448h.005c6.554 0 11.89-5.335 11.893-11.893a11.821 11.821 0 00-3.48-8.413"/>
</svg>
</div>
<div>
<div className="font-medium">WhatsApp Darurat</div>
<div className="text-sm text-gray-400">24/7 Available</div>
</div>
</motion.a> </motion.a>
))}
</div>
</div>
<motion.div {/* Links Columns */}
className="flex items-center space-x-3 text-gray-300" <div className="lg:col-span-8 grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-8 lg:gap-12">
variants={fadeIn} {Object.entries(footerLinks).map(([title, links], columnIndex) => (
initial="hidden" <div key={title} className="space-y-6">
whileInView="visible" <h4 className="font-semibold text-gray-900 dark:text-white text-sm uppercase tracking-wider">{title}</h4>
viewport={{ once: true }} <ul className="space-y-3">
> {links.map((link, index) => (
<div className="w-10 h-10 bg-primary/20 rounded-lg flex items-center justify-center"> <motion.li
<svg className="w-5 h-5 text-primary" fill="currentColor" viewBox="0 0 24 24"> key={index}
<path d="M12 2C8.13 2 5 5.13 5 9c0 5.25 7 13 7 13s7-7.75 7-13c0-3.87-3.13-7-7-7zm0 9.5c-1.38 0-2.5-1.12-2.5-2.5s1.12-2.5 2.5-2.5 2.5 1.12 2.5 2.5-1.12 2.5-2.5 2.5z"/> initial={{ opacity: 0, x: -10 }}
</svg> whileInView={{ opacity: 1, x: 0 }}
</div> viewport={{ once: true }}
<div> transition={{ delay: 0.1 + (index * 0.05) }}
<div className="font-medium">Alamat</div> >
<div className="text-sm text-gray-400">Jl. Mastrip PO Box 164, Jember</div> <a
</div> href={link.href}
</motion.div> className="text-sm text-gray-500 dark:text-gray-400 hover:text-primary dark:hover:text-primary transition-colors inline-flex items-center group"
>
<span className="relative overflow-hidden">
{link.name}
<span className="absolute bottom-0 left-0 w-full h-[1px] bg-primary transform -translate-x-full group-hover:translate-x-0 transition-transform duration-300"></span>
</span>
</a>
</motion.li>
))}
</ul>
</div> </div>
</motion.div> ))}
</div> </div>
</div> </div>
{/* Bottom Bar */} {/* Bottom Bar */}
<div className="py-6 border-t border-gray-800"> <div className="pt-8 border-t border-gray-200/50 dark:border-white/5 flex flex-col md:flex-row justify-between items-center gap-6 text-xs text-gray-500 dark:text-gray-500">
<motion.div <p>© {currentYear} PolijeCare. All rights reserved.</p>
className="flex flex-col md:flex-row justify-between items-center space-y-4 md:space-y-0" <div className="flex gap-8">
variants={fadeIn} <div className="flex items-center gap-2">
initial="hidden" <MapPin className="w-3 h-3" />
whileInView="visible" <span>Jember, East Java</span>
viewport={{ once: true }}
>
<div className="text-gray-400 text-sm">
© {currentYear} PolijeCare. All rights reserved.
</div> </div>
<div className="flex items-center space-x-6 text-gray-400 text-sm"> <div className="flex items-center gap-2">
<a href="#" className="hover:text-accent transition-colors">Privacy Policy</a> <Mail className="w-3 h-3" />
<a href="#" className="hover:text-accent transition-colors">Terms of Service</a> <span>satgasppkpt@polije.ac.id</span>
<a href="#" className="hover:text-accent transition-colors">Cookie Policy</a>
</div> </div>
</motion.div> </div>
</div> </div>
</div> </div>
</footer> </footer>

View File

@ -39,7 +39,7 @@ export function FlowButton({
{/* Circle Hover Effect */} {/* Circle Hover Effect */}
<span <span
className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-4 h-4 rounded-[50%] opacity-0 group-hover:w-[300px] group-hover:h-[300px] group-hover:opacity-100 transition-all duration-[800ms] ease-[cubic-bezier(0.19,1,0.22,1)]" className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-4 h-4 rounded-[50%] opacity-0 group-hover:w-[1200px] group-hover:h-[1200px] group-hover:opacity-100 transition-all duration-[800ms] ease-[cubic-bezier(0.19,1,0.22,1)]"
style={{ backgroundColor: hoverColorStr }} style={{ backgroundColor: hoverColorStr }}
></span> ></span>