forked from UKSOURCE/hailearning.edu.vn
featL Add news page
This commit is contained in:
23
app/blog/components/Breadcrumb.tsx
Normal file
23
app/blog/components/Breadcrumb.tsx
Normal file
@@ -0,0 +1,23 @@
|
||||
export default function Breadcrumb() {
|
||||
return (
|
||||
<section className="breadcrumb-wrapper fix bg-cover" style={{ backgroundImage: "url(/assets/img/inner-page/breadcrumb.jpg)" }}>
|
||||
<div className="shape">
|
||||
<img src="/assets/img/inner-page/shape.png" alt="img" />
|
||||
</div>
|
||||
<div className="container">
|
||||
<div className="page-heading">
|
||||
<h1 className="breadcrumb-title">Blog Stardard</h1>
|
||||
<ul className="breadcrumb-list">
|
||||
<li>
|
||||
<a href="/">Home</a>
|
||||
</li>
|
||||
<li>
|
||||
<i className="fa-solid fa-chevron-right"></i>
|
||||
</li>
|
||||
<li>Blog Stardard</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
90
app/blog/components/NewsList.tsx
Normal file
90
app/blog/components/NewsList.tsx
Normal file
@@ -0,0 +1,90 @@
|
||||
export default function NewsList() {
|
||||
return (
|
||||
<div className="col-lg-8 col-12">
|
||||
{/* News Post 1 */}
|
||||
<div className="news-standard-post">
|
||||
<div className="news-image">
|
||||
<img src="/assets/img/home-1/news/news-13.jpg" alt="img" />
|
||||
</div>
|
||||
<div className="news-content">
|
||||
<ul className="news-list">
|
||||
<li>
|
||||
<i className="fa-solid fa-user"></i> By Admin
|
||||
</li>
|
||||
<li>
|
||||
<i className="fa-solid fa-calendar-days"></i> 11 March 2025
|
||||
</li>
|
||||
<li>
|
||||
<i className="fa-solid fa-comments"></i> 0 Comments
|
||||
</li>
|
||||
</ul>
|
||||
<h3>
|
||||
<a href="/news-details">How to Avoid Common Mistakes in Visa Applications</a>
|
||||
</h3>
|
||||
<p>
|
||||
A business consultant provides expert guidance, strategic planning, and problem-solving support—helping startups avoid mistakes, grow faster, and operate more efficiently from day one.
|
||||
</p>
|
||||
<a href="/news-details" className="theme-btn">
|
||||
VIEW MORE <i className="fa-solid fa-arrow-right"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
{/* News Post 2 */}
|
||||
<div className="news-standard-post">
|
||||
<div className="news-image">
|
||||
<img src="/assets/img/home-1/news/news-14.jpg" alt="img" />
|
||||
</div>
|
||||
<div className="news-content">
|
||||
<ul className="news-list">
|
||||
<li>
|
||||
<i className="fa-solid fa-user"></i> By Admin
|
||||
</li>
|
||||
<li>
|
||||
<i className="fa-solid fa-calendar-days"></i> 11 March 2025
|
||||
</li>
|
||||
<li>
|
||||
<i className="fa-solid fa-comments"></i> 0 Comments
|
||||
</li>
|
||||
</ul>
|
||||
<h3>
|
||||
<a href="/news-details">The Role of Immigration Consultants in Your Journey</a>
|
||||
</h3>
|
||||
<p>
|
||||
Immigration consultants play a vital role in guiding applicants, simplifying complex processes, offering expert advice, and ensuring successful outcomes for study, work, or permanent residency abroad.
|
||||
</p>
|
||||
<a href="/news-details" className="theme-btn">
|
||||
VIEW MORE <i className="fa-solid fa-arrow-right"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
{/* News Post 3 */}
|
||||
<div className="news-standard-post mb-0">
|
||||
<div className="news-image">
|
||||
<img src="/assets/img/home-1/news/news-15.jpg" alt="img" />
|
||||
</div>
|
||||
<div className="news-content">
|
||||
<ul className="news-list">
|
||||
<li>
|
||||
<i className="fa-solid fa-user"></i> By Admin
|
||||
</li>
|
||||
<li>
|
||||
<i className="fa-solid fa-calendar-days"></i> 11 March 2025
|
||||
</li>
|
||||
<li>
|
||||
<i className="fa-solid fa-comments"></i> 0 Comments
|
||||
</li>
|
||||
</ul>
|
||||
<h3>
|
||||
<a href="/news-details">Latest Immigration Policy Updates You Should Know</a>
|
||||
</h3>
|
||||
<p>
|
||||
Stay informed with the latest immigration policy updates, ensuring you understand new rules, visa requirements, and opportunities that impact your study, work, or migration journey abroad.
|
||||
</p>
|
||||
<a href="/news-details" className="theme-btn">
|
||||
VIEW MORE <i className="fa-solid fa-arrow-right"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
17
app/blog/components/NewsSection.tsx
Normal file
17
app/blog/components/NewsSection.tsx
Normal file
@@ -0,0 +1,17 @@
|
||||
import NewsList from "./NewsList";
|
||||
import Sidebar from "./Sidebar";
|
||||
|
||||
export default function NewsSection() {
|
||||
return (
|
||||
<section className="news-standard-section section-padding fix">
|
||||
<div className="container">
|
||||
<div className="news-standard-wrapper">
|
||||
<div className="row g-4">
|
||||
<NewsList />
|
||||
<Sidebar />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
97
app/blog/components/Sidebar.tsx
Normal file
97
app/blog/components/Sidebar.tsx
Normal file
@@ -0,0 +1,97 @@
|
||||
export default function Sidebar() {
|
||||
return (
|
||||
<div className="col-lg-4 col-12">
|
||||
<div className="main-sideber">
|
||||
{/* Search Widget */}
|
||||
<div className="news-sideber-box">
|
||||
<div className="search-widget">
|
||||
<form action="#">
|
||||
<input type="text" placeholder="Search Blog" />
|
||||
<button type="submit">
|
||||
<i className="fa-solid fa-magnifying-glass"></i>
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{/* Categories */}
|
||||
<div className="news-sideber-box">
|
||||
<div className="wid-title">
|
||||
<h3>Cetegories</h3>
|
||||
</div>
|
||||
<div className="news-widget-categories">
|
||||
<ul>
|
||||
<li><a href="/news-details"><i className="fa-solid fa-chevrons-right"></i> Permanent Residency (PR)</a><span>(04)</span></li>
|
||||
<li><a href="/news-details"><i className="fa-solid fa-chevrons-right"></i> Immigration Policy Updates</a><span>(09)</span></li>
|
||||
<li><a href="/news-details"><i className="fa-solid fa-chevrons-right"></i> Scholarships & Grants</a><span>(00)</span></li>
|
||||
<li><a href="/news-details"><i className="fa-solid fa-chevrons-right"></i> Citizenship & Naturalization</a><span>(04)</span></li>
|
||||
<li><a href="/news-details"><i className="fa-solid fa-chevrons-right"></i> Visa Interview Preparation</a><span>(01)</span></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
{/* Recent Post */}
|
||||
<div className="news-sideber-box">
|
||||
<div className="wid-title">
|
||||
<h3>Recent Post</h3>
|
||||
</div>
|
||||
<div className="recent-post-area">
|
||||
<div className="recent-items">
|
||||
<div className="recent-thumb">
|
||||
<img src="/assets/img/inner-page/news-details/post-1.jpg" alt="img" />
|
||||
</div>
|
||||
<div className="recent-content">
|
||||
<h6>
|
||||
<a href="/news-details">Top Countries for Higher Education in 2025</a>
|
||||
</h6>
|
||||
<ul>
|
||||
<li>March 26, 2025</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div className="recent-items">
|
||||
<div className="recent-thumb">
|
||||
<img src="/assets/img/inner-page/news-details/post-2.jpg" alt="img" />
|
||||
</div>
|
||||
<div className="recent-content">
|
||||
<h6>
|
||||
<a href="/news-details">The Benefits of Hiring a Visa Consultant</a>
|
||||
</h6>
|
||||
<ul>
|
||||
<li>March 26, 2025</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div className="recent-items">
|
||||
<div className="recent-thumb">
|
||||
<img src="/assets/img/inner-page/news-details/post-3.jpg" alt="img" />
|
||||
</div>
|
||||
<div className="recent-content">
|
||||
<h6>
|
||||
<a href="/news-details">How to Prepare for Your Immigration Interview</a>
|
||||
</h6>
|
||||
<ul>
|
||||
<li>March 26, 2025</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/* Tag Cloud */}
|
||||
<div className="news-sideber-box mb-0">
|
||||
<div className="wid-title">
|
||||
<h3>Tag Cloud</h3>
|
||||
</div>
|
||||
<div className="news-widget-categories">
|
||||
<div className="tagcloud">
|
||||
<a href="/news-details">WorkVisa</a>
|
||||
<a href="/news-details">FamilyVisa</a>
|
||||
<a href="/news-details">StudentVisa</a>
|
||||
<a href="/news-details">VisaUpdates</a>
|
||||
<a href="/news-details">TravelVisa</a>
|
||||
<a href="/news-details">StudyAbroad</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,144 +1,11 @@
|
||||
"use client";
|
||||
|
||||
import { useState } from "react";
|
||||
import blogData from "./blog.json";
|
||||
|
||||
export default function BlogPage() {
|
||||
const [selectedCategory, setSelectedCategory] = useState("all");
|
||||
|
||||
const filteredPosts =
|
||||
selectedCategory === "all"
|
||||
? blogData.posts
|
||||
: blogData.posts.filter(
|
||||
(post) => post.category.toLowerCase() === selectedCategory,
|
||||
);
|
||||
import Breadcrumb from "./components/Breadcrumb";
|
||||
import NewsSection from "./components/NewsSection";
|
||||
|
||||
export default function NewsPage() {
|
||||
return (
|
||||
<div className="container mx-auto px-4 py-8">
|
||||
<div className="max-w-6xl mx-auto">
|
||||
{/* Header */}
|
||||
<div className="text-center mb-12">
|
||||
<h1 className="text-4xl font-bold text-gray-900 mb-4">
|
||||
{blogData.title}
|
||||
</h1>
|
||||
<p className="text-xl text-gray-600">{blogData.subtitle}</p>
|
||||
</div>
|
||||
|
||||
{/* Featured Post */}
|
||||
<div className="mb-12">
|
||||
<div className="bg-gradient-to-r from-blue-600 to-purple-600 rounded-lg p-8 text-white">
|
||||
<div className="flex items-center mb-4">
|
||||
<span className="bg-yellow-400 text-black px-3 py-1 rounded-full text-sm font-medium mr-4">
|
||||
Nổi bật
|
||||
</span>
|
||||
<span className="text-blue-100">
|
||||
{blogData.featured.category}
|
||||
</span>
|
||||
</div>
|
||||
<h2 className="text-3xl font-bold mb-4">
|
||||
{blogData.featured.title}
|
||||
</h2>
|
||||
<p className="text-blue-100 mb-6 text-lg">
|
||||
{blogData.featured.excerpt}
|
||||
</p>
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex items-center text-blue-100">
|
||||
<span className="mr-4">👤 {blogData.featured.author}</span>
|
||||
<span className="mr-4">📅 {blogData.featured.date}</span>
|
||||
<span>⏱️ {blogData.featured.readTime}</span>
|
||||
</div>
|
||||
<button className="bg-white text-blue-600 px-6 py-2 rounded-lg hover:bg-blue-50 transition-colors">
|
||||
Đọc thêm
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Category Filter */}
|
||||
<div className="mb-8">
|
||||
<div className="flex flex-wrap gap-4 justify-center">
|
||||
{blogData.categories.map((category) => (
|
||||
<button
|
||||
key={category.slug}
|
||||
onClick={() => setSelectedCategory(category.slug)}
|
||||
className={`px-6 py-2 rounded-full transition-colors ${
|
||||
selectedCategory === category.slug
|
||||
? "bg-blue-600 text-white"
|
||||
: "bg-gray-100 text-gray-700 hover:bg-gray-200"
|
||||
}`}
|
||||
>
|
||||
{category.name} ({category.count})
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Blog Posts Grid */}
|
||||
<div className="grid md:grid-cols-2 lg:grid-cols-3 gap-8">
|
||||
{filteredPosts.map((post) => (
|
||||
<article
|
||||
key={post.id}
|
||||
className="bg-white rounded-lg shadow-md overflow-hidden hover:shadow-lg transition-shadow"
|
||||
>
|
||||
{/* Post Image */}
|
||||
<div className="h-48 bg-gray-200 flex items-center justify-center">
|
||||
<span className="text-gray-400">📷 {post.category}</span>
|
||||
</div>
|
||||
|
||||
{/* Post Content */}
|
||||
<div className="p-6">
|
||||
{/* Category & Date */}
|
||||
<div className="flex items-center justify-between mb-3">
|
||||
<span className="bg-blue-100 text-blue-800 px-2 py-1 rounded text-sm">
|
||||
{post.category}
|
||||
</span>
|
||||
<span className="text-gray-500 text-sm">{post.date}</span>
|
||||
</div>
|
||||
|
||||
{/* Title */}
|
||||
<h3 className="text-xl font-semibold text-gray-900 mb-3 line-clamp-2">
|
||||
{post.title}
|
||||
</h3>
|
||||
|
||||
{/* Excerpt */}
|
||||
<p className="text-gray-700 mb-4 line-clamp-3">
|
||||
{post.excerpt}
|
||||
</p>
|
||||
|
||||
{/* Tags */}
|
||||
<div className="flex flex-wrap gap-2 mb-4">
|
||||
{post.tags.map((tag, index) => (
|
||||
<span
|
||||
key={index}
|
||||
className="bg-gray-100 text-gray-600 px-2 py-1 rounded text-xs"
|
||||
>
|
||||
#{tag}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Meta Info */}
|
||||
<div className="flex items-center justify-between text-sm text-gray-500">
|
||||
<span>👤 {post.author}</span>
|
||||
<span>⏱️ {post.readTime}</span>
|
||||
</div>
|
||||
|
||||
{/* Read More Button */}
|
||||
<button className="w-full mt-4 bg-blue-600 text-white py-2 px-4 rounded-lg hover:bg-blue-700 transition-colors">
|
||||
Đọc thêm
|
||||
</button>
|
||||
</div>
|
||||
</article>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Load More */}
|
||||
<div className="text-center mt-12">
|
||||
<button className="bg-gray-100 text-gray-700 px-8 py-3 rounded-lg hover:bg-gray-200 transition-colors">
|
||||
Xem thêm bài viết
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<>
|
||||
<Breadcrumb />
|
||||
<NewsSection />
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,26 +1 @@
|
||||
@import "tailwindcss";
|
||||
|
||||
:root {
|
||||
--background: #ffffff;
|
||||
--foreground: #171717;
|
||||
}
|
||||
|
||||
@theme inline {
|
||||
--color-background: var(--background);
|
||||
--color-foreground: var(--foreground);
|
||||
--font-sans: var(--font-geist-sans);
|
||||
--font-mono: var(--font-geist-mono);
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--background: #0a0a0a;
|
||||
--foreground: #ededed;
|
||||
}
|
||||
}
|
||||
|
||||
body {
|
||||
background: var(--background);
|
||||
color: var(--foreground);
|
||||
font-family: Arial, Helvetica, sans-serif;
|
||||
}
|
||||
@import "tailwindcss";
|
||||
@@ -1,18 +1,9 @@
|
||||
import type { Metadata } from "next";
|
||||
import { Geist, Geist_Mono } from "next/font/google";
|
||||
import "./globals.css";
|
||||
|
||||
import Header from "./components/Header";
|
||||
import Footer from "./components/Footer";
|
||||
|
||||
const geistSans = Geist({
|
||||
variable: "--font-geist-sans",
|
||||
subsets: ["latin"],
|
||||
});
|
||||
|
||||
const geistMono = Geist_Mono({
|
||||
variable: "--font-geist-mono",
|
||||
subsets: ["latin"],
|
||||
});
|
||||
import Script from "next/script";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "VisaService - Dịch vụ visa uy tín",
|
||||
@@ -27,12 +18,39 @@ export default function RootLayout({
|
||||
}>) {
|
||||
return (
|
||||
<html lang="vi">
|
||||
<body
|
||||
className={`${geistSans.variable} ${geistMono.variable} antialiased bg-gray-50`}
|
||||
>
|
||||
<head>
|
||||
{/* Nhúng các file CSS template như news.html */}
|
||||
<link rel="shortcut icon" href="/assets/img/favicon.png" />
|
||||
<link rel="stylesheet" href="/assets/css/bootstrap.min.css" />
|
||||
<link rel="stylesheet" href="/assets/css/all.min.css" />
|
||||
<link rel="stylesheet" href="/assets/css/animate.css" />
|
||||
<link rel="stylesheet" href="/assets/css/magnific-popup.css" />
|
||||
<link rel="stylesheet" href="/assets/css/meanmenu.css" />
|
||||
<link rel="stylesheet" href="/assets/css/odometer.css" />
|
||||
<link rel="stylesheet" href="/assets/css/swiper-bundle.min.css" />
|
||||
<link rel="stylesheet" href="/assets/css/nice-select.css" />
|
||||
<link rel="stylesheet" href="/assets/css/main.css" />
|
||||
</head>
|
||||
<body className={`antialiased bg-gray-50`}>
|
||||
<Header />
|
||||
<main className="min-h-screen">{children}</main>
|
||||
<Footer />
|
||||
{/* Nhúng các script JS giống news.html */}
|
||||
<Script src="/assets/js/jquery-3.7.1.min.js" strategy="beforeInteractive" />
|
||||
<Script src="/assets/js/viewport.jquery.js" strategy="afterInteractive" />
|
||||
<Script src="/assets/js/bootstrap.bundle.min.js" strategy="afterInteractive" />
|
||||
<Script src="/assets/js/jquery.nice-select.min.js" strategy="afterInteractive" />
|
||||
<Script src="/assets/js/jquery.waypoints.js" strategy="afterInteractive" />
|
||||
<Script src="/assets/js/odometer.min.js" strategy="afterInteractive" />
|
||||
<Script src="/assets/js/swiper-bundle.min.js" strategy="afterInteractive" />
|
||||
<Script src="/assets/js/jquery.meanmenu.min.js" strategy="afterInteractive" />
|
||||
<Script src="/assets/js/jquery.magnific-popup.min.js" strategy="afterInteractive" />
|
||||
<Script src="/assets/js/wow.min.js" strategy="afterInteractive" />
|
||||
<Script src="/assets/js/gsap.js" strategy="afterInteractive" />
|
||||
<Script src="/assets/js/lenis.min.js" strategy="afterInteractive" />
|
||||
<Script src="/assets/js/ScrollTrigger.min.js" strategy="afterInteractive" />
|
||||
<Script src="/assets/js/SplitText.min.js" strategy="afterInteractive" />
|
||||
<Script src="/assets/js/main.js" strategy="afterInteractive" />
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user