forked from UKSOURCE/hailearning.edu.vn
feat: create Partnership and Blog functional components
This commit is contained in:
13
app/components/blog/BlogSidebar.tsx
Normal file
13
app/components/blog/BlogSidebar.tsx
Normal file
@@ -0,0 +1,13 @@
|
||||
import NewsletterWidget from "./NewsletterWidget";
|
||||
import ResearcherSpotlight from "./ResearcherSpotlight";
|
||||
import UpcomingEvents from "./UpcomingEvents";
|
||||
|
||||
export default function BlogSidebar() {
|
||||
return (
|
||||
<aside className="w-full lg:w-[400px] shrink-0 space-y-8">
|
||||
<NewsletterWidget />
|
||||
<ResearcherSpotlight />
|
||||
<UpcomingEvents />
|
||||
</aside>
|
||||
);
|
||||
}
|
||||
21
app/components/blog/CategoryFilters.tsx
Normal file
21
app/components/blog/CategoryFilters.tsx
Normal file
@@ -0,0 +1,21 @@
|
||||
const categories = ["All News", "Campus", "Research", "Partnerships", "Events"];
|
||||
|
||||
export default function CategoryFilters() {
|
||||
return (
|
||||
<div id="category-filters" className="flex flex-wrap items-center gap-3 mb-10 pb-6 border-b border-ui-border">
|
||||
{categories.map((cat, i) => (
|
||||
<button
|
||||
key={cat}
|
||||
style={{ borderRadius: "9999px", fontSize: "0.8rem" }}
|
||||
className={
|
||||
i === 0
|
||||
? "px-6 py-2 bg-brand-blue text-white text-sm font-semibold shadow-sm transition-colors"
|
||||
: "px-6 py-2 bg-white border border-ui-border text-ui-text hover:border-brand-blue hover:text-brand-blue text-sm font-medium transition-colors"
|
||||
}
|
||||
>
|
||||
{cat}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
44
app/components/blog/FeaturedHero.tsx
Normal file
44
app/components/blog/FeaturedHero.tsx
Normal file
@@ -0,0 +1,44 @@
|
||||
export default function FeaturedHero() {
|
||||
return (
|
||||
<section id="featured-hero" className="w-full bg-white border-b border-ui-border mb-12">
|
||||
<div className="max-w-[1440px] mx-auto">
|
||||
<div className="flex flex-col lg:flex-row min-h-[500px]">
|
||||
{/* Left: Content */}
|
||||
<div className="w-full lg:w-1/2 p-8 lg:p-16 flex flex-col justify-center">
|
||||
<span className="inline-block px-3 py-1 bg-brand-light text-brand-blue border border-brand-blue/20 text-xs font-semibold mb-4 w-fit" style={{ borderRadius: "6px" }}>
|
||||
Featured Research
|
||||
</span>
|
||||
<div className="blog-heading text-ui-text tracking-tight mb-6 leading-tight font-bold">
|
||||
Pioneering Sustainable Urban Development in the Heart of Paris
|
||||
</div>
|
||||
<p className="text-lg text-ui-muted mb-8 leading-relaxed">
|
||||
Our latest collaborative research initiative uncovers groundbreaking methods for integrating green infrastructure into historic urban environments, setting a new standard for European cities.
|
||||
</p>
|
||||
<div className="flex items-center gap-4 text-sm text-ui-muted mb-8 mt-4">
|
||||
<div className="flex items-center gap-2">
|
||||
<img src="https://storage.googleapis.com/uxpilot-auth.appspot.com/avatars/avatar-1.jpg" alt="Author" className="w-8 h-8 rounded-full border border-ui-border" />
|
||||
<span className="font-medium text-ui-text">Dr. Amélie Dubois</span>
|
||||
</div>
|
||||
<span>•</span>
|
||||
<span>October 15, 2024</span>
|
||||
<span>•</span>
|
||||
<span>5 min read</span>
|
||||
</div>
|
||||
<a href="#" className="inline-flex items-center justify-center px-5 py-3 text-white font-semibold text-sm hover:bg-brand-hover transition-colors shadow-sm w-fit gap-2" style={{ borderRadius: "5px", backgroundColor: "rgb(38, 60, 111)" }}>
|
||||
Read Full Story <i className="fas fa-arrow-right text-xs"></i>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
{/* Right: Image */}
|
||||
<div className="w-full lg:w-1/2 bg-gray-100 relative min-h-[300px] lg:min-h-full">
|
||||
<img
|
||||
className="absolute inset-0 w-full h-full object-cover"
|
||||
src="https://storage.googleapis.com/uxpilot-auth.appspot.com/75c7c284e8-18119bca345a35938b88.png"
|
||||
alt="Aerial view of Paris with sustainable green roofs and modern eco-friendly architecture blending with historic buildings"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
48
app/components/blog/NewsCard.tsx
Normal file
48
app/components/blog/NewsCard.tsx
Normal file
@@ -0,0 +1,48 @@
|
||||
type NewsCardProps = {
|
||||
category: string;
|
||||
date: string;
|
||||
title: string;
|
||||
excerpt: string;
|
||||
image?: string;
|
||||
icon?: string;
|
||||
};
|
||||
|
||||
export default function NewsCard({ category, date, title, excerpt, image, icon }: NewsCardProps) {
|
||||
return (
|
||||
<article className="bg-white rounded-xl border border-ui-border overflow-hidden shadow-soft hover:shadow-hover hover:border-brand-blue/50 transition-all group flex flex-col">
|
||||
{/* Thumbnail */}
|
||||
<div className="h-48 overflow-hidden relative">
|
||||
{image ? (
|
||||
<img
|
||||
className="w-full h-full object-cover group-hover:scale-105 transition-transform duration-500"
|
||||
src={image}
|
||||
alt={title}
|
||||
/>
|
||||
) : (
|
||||
<div className="w-full h-full bg-brand-light flex items-center justify-center">
|
||||
<i className={`${icon} text-4xl text-brand-blue/40`}></i>
|
||||
</div>
|
||||
)}
|
||||
<div className="absolute top-4 left-4">
|
||||
<span className="px-3 py-1 bg-white/90 backdrop-blur-sm text-brand-blue rounded-md text-xs font-bold shadow-sm">
|
||||
{category}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Content */}
|
||||
<div className="p-6 flex flex-col flex-1">
|
||||
<div className="text-xs text-ui-muted mb-3 flex items-center gap-2">
|
||||
<i className="far fa-calendar"></i> {date}
|
||||
</div>
|
||||
<div className="blog-card-title text-ui-text group-hover:text-brand-blue transition-colors mb-3 leading-tight font-bold">
|
||||
{title}
|
||||
</div>
|
||||
<p className="text-sm text-ui-muted mb-6 flex-1 line-clamp-3">{excerpt}</p>
|
||||
<a href="#" className="text-sm font-bold text-brand-blue flex items-center gap-1 group-hover:gap-2 transition-all pt-4">
|
||||
Read more <i className="fas fa-arrow-right text-xs"></i>
|
||||
</a>
|
||||
</div>
|
||||
</article>
|
||||
);
|
||||
}
|
||||
59
app/components/blog/NewsGrid.tsx
Normal file
59
app/components/blog/NewsGrid.tsx
Normal file
@@ -0,0 +1,59 @@
|
||||
import NewsCard from "./NewsCard";
|
||||
|
||||
const news = [
|
||||
{
|
||||
category: "Campus",
|
||||
date: "Oct 12, 2024",
|
||||
title: "New Liberal Arts Library Wing Opens to Students",
|
||||
excerpt: "The state-of-the-art facility provides expanded collaborative spaces and access to over 50,000 new digital and print resources for our growing student body.",
|
||||
image: "https://storage.googleapis.com/uxpilot-auth.appspot.com/8eafd095d9-314bdad36b2119266084.png",
|
||||
},
|
||||
{
|
||||
category: "Partnerships",
|
||||
date: "Oct 10, 2024",
|
||||
title: "ULP Announces Strategic Alliance with TechGlobal Institute",
|
||||
excerpt: "A new partnership aimed at bridging the gap between liberal arts education and emerging technological paradigms in the 21st century.",
|
||||
icon: "fas fa-handshake",
|
||||
},
|
||||
{
|
||||
category: "Events",
|
||||
date: "Oct 05, 2024",
|
||||
title: "Annual Global Ethics Symposium Draws Record Attendance",
|
||||
excerpt: "Scholars from over 40 countries gathered at ULP this weekend to discuss the evolving landscape of international human rights and digital privacy.",
|
||||
image: "https://storage.googleapis.com/uxpilot-auth.appspot.com/fc832714d8-ee7527b4d94c300aae71.png",
|
||||
},
|
||||
{
|
||||
category: "Research",
|
||||
date: "Sep 28, 2024",
|
||||
title: "Department of Sociology Publishes Landmark Study on Urban Migration",
|
||||
excerpt: "A comprehensive 5-year study reveals shifting demographic patterns in post-industrial European cities, highlighting new socio-economic challenges.",
|
||||
icon: "fas fa-flask",
|
||||
},
|
||||
];
|
||||
|
||||
export default function NewsGrid() {
|
||||
return (
|
||||
<div className="flex-1">
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-6 mb-12">
|
||||
{news.map((item) => (
|
||||
<NewsCard key={item.title} {...item} />
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Pagination */}
|
||||
<div className="flex justify-center items-center gap-2 border-t border-ui-border pt-8">
|
||||
<button className="pg-btn w-10 h-10 flex items-center justify-center border border-ui-border text-ui-muted transition-colors disabled:opacity-50" disabled>
|
||||
<i className="fas fa-chevron-left"></i>
|
||||
</button>
|
||||
<button className="pg-btn pg-active w-10 h-10 flex items-center justify-center text-white font-bold">1</button>
|
||||
<button className="pg-btn w-10 h-10 flex items-center justify-center border border-ui-border text-ui-text transition-colors font-medium">2</button>
|
||||
<button className="pg-btn w-10 h-10 flex items-center justify-center border border-ui-border text-ui-text transition-colors font-medium">3</button>
|
||||
<span className="text-ui-muted mx-2">...</span>
|
||||
<button className="pg-btn w-10 h-10 flex items-center justify-center border border-ui-border text-ui-text transition-colors font-medium">12</button>
|
||||
<button className="pg-btn w-10 h-10 flex items-center justify-center border border-ui-border text-ui-text transition-colors">
|
||||
<i className="fas fa-chevron-right"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
37
app/components/blog/NewsletterWidget.tsx
Normal file
37
app/components/blog/NewsletterWidget.tsx
Normal file
@@ -0,0 +1,37 @@
|
||||
export default function NewsletterWidget() {
|
||||
return (
|
||||
<div className="bg-brand-blue rounded-xl p-8 text-white shadow-hover relative overflow-hidden folder-tab">
|
||||
<div className="relative z-10">
|
||||
<div className="blog-widget-title font-bold mb-3">Stay Informed</div>
|
||||
<p className="text-sm text-brand-light/80 mb-6 leading-relaxed ">
|
||||
Subscribe to our weekly newsletter for the latest research updates, campus news, and upcoming events.
|
||||
</p>
|
||||
<form className="space-y-4">
|
||||
<div>
|
||||
<input
|
||||
type="email"
|
||||
placeholder="Enter your email address"
|
||||
className="w-full px-4 py-3 mt-4 bg-white/10 border border-white/20 rounded-lg text-white placeholder-white/50 focus:outline-none focus:border-white focus:ring-1 focus:ring-white text-sm"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<button
|
||||
type="submit"
|
||||
className="w-full py-3 bg-white text-brand-blue rounded-lg font-bold hover:bg-gray-50 transition-colors text-sm shadow-sm"
|
||||
>
|
||||
Subscribe Now
|
||||
</button>
|
||||
</form>
|
||||
<p className="text-xs text-brand-light/60 mt-4 text-center">
|
||||
By subscribing, you agree to our{" "}
|
||||
<a href="#" style={{ color: "inherit", textDecoration: "underline" }}>Privacy Policy</a>.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Decorative background element */}
|
||||
<div className="absolute -bottom-12 -right-12 text-white/5 text-9xl">
|
||||
<i className="far fa-envelope"></i>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
47
app/components/blog/ResearcherSpotlight.tsx
Normal file
47
app/components/blog/ResearcherSpotlight.tsx
Normal file
@@ -0,0 +1,47 @@
|
||||
const researchers = [
|
||||
{
|
||||
name: "Dr. Sarah Jenkins",
|
||||
field: "Cognitive Linguistics",
|
||||
bio: "Exploring the intersection of language processing and modern ethical frameworks in digital communication.",
|
||||
avatar: "https://storage.googleapis.com/uxpilot-auth.appspot.com/avatars/avatar-5.jpg",
|
||||
},
|
||||
{
|
||||
name: "Prof. Marcus Chen",
|
||||
field: "Economic History",
|
||||
bio: "Recent recipient of the European Heritage Grant for his work on interwar economic policies.",
|
||||
avatar: "https://storage.googleapis.com/uxpilot-auth.appspot.com/avatars/avatar-4.jpg",
|
||||
},
|
||||
{
|
||||
name: "Dr. Elena Rostova",
|
||||
field: "Political Science",
|
||||
bio: "Leading the new comparative study on post-war democratic institutions across Western Europe.",
|
||||
avatar: "https://storage.googleapis.com/uxpilot-auth.appspot.com/avatars/avatar-6.jpg",
|
||||
},
|
||||
];
|
||||
|
||||
export default function ResearcherSpotlight() {
|
||||
return (
|
||||
<div className="bg-white rounded-xl border border-ui-border shadow-soft p-6">
|
||||
<div className="flex items-center justify-between mb-6 pb-4 border-b border-ui-border">
|
||||
<div className="blog-widget-title font-bold text-ui-text">Researcher Spotlight</div>
|
||||
<a href="#" className="text-sm text-brand-blue font-medium hover:underline">View All</a>
|
||||
</div>
|
||||
<div className="space-y-6">
|
||||
{researchers.map((r) => (
|
||||
<div key={r.name} className="flex gap-4 items-start group cursor-pointer">
|
||||
<img
|
||||
src={r.avatar}
|
||||
alt={r.name}
|
||||
className="w-16 h-16 rounded-lg object-cover border border-ui-border group-hover:border-brand-blue transition-colors"
|
||||
/>
|
||||
<div>
|
||||
<div className="font-bold text-ui-text text-sm group-hover:text-brand-blue transition-colors">{r.name}</div>
|
||||
<p className="text-xs text-brand-blue font-medium mb-1">{r.field}</p>
|
||||
<p className="text-xs text-ui-muted line-clamp-2">{r.bio}</p>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
40
app/components/blog/UpcomingEvents.tsx
Normal file
40
app/components/blog/UpcomingEvents.tsx
Normal file
@@ -0,0 +1,40 @@
|
||||
const events = [
|
||||
{
|
||||
month: "Nov",
|
||||
day: "12",
|
||||
title: "Open Campus Day",
|
||||
time: "09:00 AM - 04:00 PM",
|
||||
},
|
||||
{
|
||||
month: "Nov",
|
||||
day: "18",
|
||||
title: "Guest Lecture: Future of AI in Arts",
|
||||
time: "06:00 PM - Main Hall",
|
||||
},
|
||||
];
|
||||
|
||||
export default function UpcomingEvents() {
|
||||
return (
|
||||
<div className="bg-white rounded-xl border border-ui-border shadow-soft p-6">
|
||||
<div className="blog-widget-title font-bold text-ui-text mb-6 pb-4 border-b border-ui-border">
|
||||
Upcoming Events
|
||||
</div>
|
||||
<ul className="space-y-4">
|
||||
{events.map((e) => (
|
||||
<li key={e.title} className="flex gap-4">
|
||||
<div className="flex flex-col items-center justify-center w-12 h-12 bg-brand-light rounded-lg border border-brand-blue/20 shrink-0">
|
||||
<span className="text-xs font-bold text-brand-blue uppercase">{e.month}</span>
|
||||
<span className="text-lg font-bold text-ui-text leading-none">{e.day}</span>
|
||||
</div>
|
||||
<div>
|
||||
<div className="text-sm font-bold text-ui-text hover:text-brand-blue cursor-pointer transition-colors">{e.title}</div>
|
||||
<p className="text-xs text-ui-muted mt-1">
|
||||
<i className="far fa-clock mr-1"></i>{e.time}
|
||||
</p>
|
||||
</div>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user