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
1 change: 1 addition & 0 deletions google6ea4f563230cd745.html
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
google-site-verification: google6ea4f563230cd745.html
76 changes: 37 additions & 39 deletions src/components/PopularPost/Popular.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,49 +31,47 @@ const Popular = ({ data }) => {
],
};
return (
<>
<section className="popular">
<HeadingSection title="Popular" />
<div className="content">
<Slider {...settings}>
{data?.map((val) => {
return (
<Link
to={`/${val.slug}/detail`}
className="text-black"
title={val?.title}
key={val?.id}
>
<div className="items">
<div className="shadow box">
<div className="images row">
<div className="img">
<img src={val?.photo} alt="" loading="lazy" />
</div>
<div className="category category1">
<span>{val?.category?.name}</span>
</div>
<section className="popular">
<HeadingSection title="Popular" />
<div className="content">
<Slider {...settings}>
{data?.map((val) => {
return (
<Link
to={`/${val.slug}/detail`}
className="text-black"
title={val?.title}
key={val?.id}
>
<div className="items">
<div className="shadow box">
<div className="images row">
<div className="img">
<img src={val?.photo} alt="" loading="lazy" />
</div>
<div className="text row">
<h1 className="truncate title">{val?.title}</h1>
<Flex className="date" gap="small" align="center">
<CalendarOutlined />
<label>{val?.created_at}</label>
</Flex>
<Flex className="comment" gap="small" align="center">
<EyeOutlined />
<label>{val?.view}</label>
</Flex>
<div className="category category1">
<span>{val?.category?.name}</span>
</div>
</div>
<div className="text row">
<h1 className="truncate title">{val?.title}</h1>
<Flex className="date" gap="small" align="center">
<CalendarOutlined />
<label>{val?.created_at}</label>
</Flex>
<Flex className="comment" gap="small" align="center">
<EyeOutlined />
<label>{val?.view}</label>
</Flex>
</div>
</div>
</Link>
);
})}
</Slider>
</div>
</section>
</>
</div>
</Link>
);
})}
</Slider>
</div>
</section>
);
};

Expand Down
4 changes: 3 additions & 1 deletion src/layouts/app-layouts/user-layouts/FooterNav.jsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { Layout } from "antd";
import { useMemo } from "react";
const { Footer } = Layout;
const FooterNav = () => {
return <Footer className="bg-slate-200 text-center">©Copyright by dev3h 2023 </Footer>;
const currentYear = useMemo(() => new Date().getFullYear(), []);
return <Footer className="bg-slate-200 text-center">©Copyright by dev3h {currentYear} </Footer>;
};

export default FooterNav;
Original file line number Diff line number Diff line change
@@ -1,28 +1,61 @@
import { useEffect } from "react";
import { useEffect, useState } from "react";
import { Flex } from "antd";
import { DownOutlined } from "@ant-design/icons";
import "./menu.css";
import { useUserStore } from "@/stores/user-store/UserStore";
import { Link } from "react-router-dom";

const GroupCategoryMenu = () => {
const { groupCategories, getGroupCategories } = useUserStore();
const { groups, getAllGroups } = useUserStore();
const [openDropdown, setOpenDropdown] = useState(null);

useEffect(() => {
getGroupCategories();
}, []);
getAllGroups();
}, [getAllGroups]);

const handleMouseEnter = (groupId) => {
setOpenDropdown(groupId);
};

const handleMouseLeave = () => {
setOpenDropdown(null);
};

return (
<Flex className="flex-1 px-4" justify="center" gap="small">
{groupCategories?.map((val) => {
{groups?.map((group) => {
const hasCategories = group?.categories && group.categories.length > 0;
return (
<div
className="menu-item w-[200px] text-center cursor-pointer transition-all"
key={val?.id}
className="menu-item relative w-[200px] text-center cursor-pointer transition-all"
key={group?.id}
onMouseEnter={() => handleMouseEnter(group?.id)}
onMouseLeave={handleMouseLeave}
>
<Link
className="inline-block w-full h-full text-black transition-all hover:text-orange-400"
to={`/group/${val?.slug}`}
className="inline-block w-full h-full text-black transition-all hover:text-orange-400 py-2"
to={`/group/${group?.slug}`}
>
{val?.name}
<Flex justify="center" align="center" gap="small">
<span>{group?.name}</span>
{hasCategories && <DownOutlined className="text-xs" />}
</Flex>
</Link>

{/* Dropdown menu for categories */}
{hasCategories && openDropdown === group?.id && (
<div className="absolute top-full left-0 w-full bg-white shadow-lg rounded-md py-2 z-50 border border-gray-200">
{group.categories.map((category) => (
<Link
key={category?.id}
to={`/category/${category?.slug}`}
className="block px-4 py-2 text-black hover:bg-gray-100 hover:text-orange-400 transition-all"
>
{category?.name}
</Link>
))}
</div>
)}
</div>
);
})}
Expand Down
10 changes: 10 additions & 0 deletions src/services/userServices/groupServices.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,16 @@ class groupServices {
console.log(error);
}
}
static async getAllGroups() {
try {
const response = await axiosInstance.get(`/user/group`);
const data = response.data;
return data;
} catch (error) {
console.log(error);
Copy link

Copilot AI Dec 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The getAllGroups method does not return a value when an error occurs. This could result in undefined being returned to the caller. Consider returning an empty array or a default value for consistent error handling.

static async getAllGroups() {
  try {
    const response = await axiosInstance.get(`/user/group`);
    const data = response.data;
    return data;
  } catch (error) {
    console.log(error);
    return []; // Return empty array on error
  }
}
Suggested change
console.log(error);
console.log(error);
return [];

Copilot uses AI. Check for mistakes.
return [];
}
}
}

export default groupServices;
11 changes: 11 additions & 0 deletions src/stores/user-store/UserStore.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { create } from "zustand";
import postServices from "@/services/userServices/postServices";
import userAuthServices from "@/services/authServices/userAuthServices";
import groupServices from "@/services/userServices/groupServices";

export const useUserAuthStore = create((set) => ({
token: JSON.parse(localStorage.getItem("user"))?.token,
Expand Down Expand Up @@ -28,6 +29,7 @@ export const useUserAuthStore = create((set) => ({

export const useUserStore = create((set) => ({
groupCategories: [],
groups: [],
userIP: "",
setGroupCategories: (groupCategories) => set({ groupCategories }),
setUserIP: (userIP) => set({ userIP }),
Expand All @@ -40,6 +42,15 @@ export const useUserStore = create((set) => ({
console.log(error);
}
},
getAllGroups: async () => {
try {
const response = await groupServices.getAllGroups();
set({ groups: response });
} catch (error) {
console.log(error);
set({ groups: [] });
}
Copy link

Copilot AI Dec 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The getAllGroups method does not return a value when an error occurs, which could lead to the store state being set to undefined. Consider returning an empty array or rethrowing the error for proper error handling.

getAllGroups: async () => {
  try {
    const response = await groupServices.getAllGroups();
    set({ groups: response });
  } catch (error) {
    console.log(error);
    set({ groups: [] }); // Set to empty array on error
  }
},
Suggested change
}
set({ groups: [] }); // Set to empty array on error

Copilot uses AI. Check for mistakes.
},
getUserIP: async () => {
try {
const response = await fetch("/ipify");
Expand Down
Loading