mirror of
https://github.com/rgrgogu/new_starr.git
synced 2026-09-27 00:12:54 +08:00
testing 127.0.0.1 issue
Signed-off-by: Kenneth Obsequio <k80308392@gmail.com>
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import { useEffect, useMemo, useState } from "react";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { House, Timer, ChevronLeft, ChevronRight, LockIcon, Tag, Check, ShoppingCart } from "lucide-react";
|
||||
import { House, Timer, ChevronLeft, ChevronRight, LockIcon, Tag, Tags, Check, ShoppingCart } from "lucide-react";
|
||||
import AppBreadcrumb from "@/components/generic/Breadcrumb/AppBreadcrumb";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import {
|
||||
@@ -20,6 +20,7 @@ import { resolveTierBadge } from "@/utils/tierBadge.util";
|
||||
import { Building2 } from "lucide-react";
|
||||
import { useClientAdvertisements } from "@/contexts/ClientAdvertisementContext";
|
||||
import { Banner, BannerSkeleton } from "@/components/generic/Blocks/Client/Advertisements/Banner";
|
||||
import { GitBranch } from "lucide-react";
|
||||
|
||||
// ─── Helpers ──────────────────────────────────────────────────────────────────
|
||||
|
||||
@@ -37,8 +38,8 @@ const ITEMS_PER_PAGE = 10;
|
||||
// ─── Course Card ──────────────────────────────────────────────────────────────
|
||||
|
||||
const CourseCard = ({ course, tierMap, onViewDetails }) => {
|
||||
const slug = course.subscription ?? "free";
|
||||
const locked = course.is_locked;
|
||||
const slug = course.subscription ?? "free";
|
||||
const locked = course.is_locked;
|
||||
const duration = formatDuration(course.duration_seconds);
|
||||
const { rank, label, cls } = resolveTierBadge(slug, tierMap);
|
||||
|
||||
@@ -58,11 +59,14 @@ const CourseCard = ({ course, tierMap, onViewDetails }) => {
|
||||
{locked ? <LockIcon className="size-3" /> : <Tag className="size-3" />}
|
||||
{label}
|
||||
</Badge>
|
||||
{course.level && (
|
||||
<Badge variant="outline">{course.level.charAt(0).toUpperCase() + course.level.slice(1)}</Badge>
|
||||
{course.level && !locked && (
|
||||
<Badge variant="outline"><GitBranch />{course.level.charAt(0).toUpperCase() + course.level.slice(1)}</Badge>
|
||||
)}
|
||||
{(course.categories ?? []).map((cat) => (
|
||||
<Badge key={cat.id} variant="outline"><Tags /> {cat.name}</Badge>
|
||||
))}
|
||||
{locked && (
|
||||
<Badge variant="secondary" className="ml-auto">
|
||||
<Badge variant="secondary">
|
||||
<LockIcon className="size-3" /> Locked
|
||||
</Badge>
|
||||
)}
|
||||
@@ -113,7 +117,7 @@ const CourseCardSkeleton = () => (
|
||||
|
||||
const Pagination = ({ currentPage, totalPages, totalItems, itemsPerPage, onPageChange }) => {
|
||||
const start = (currentPage - 1) * itemsPerPage + 1;
|
||||
const end = Math.min(currentPage * itemsPerPage, totalItems);
|
||||
const end = Math.min(currentPage * itemsPerPage, totalItems);
|
||||
|
||||
const getPages = () => {
|
||||
const pages = [];
|
||||
@@ -165,12 +169,12 @@ const CoursesList = () => {
|
||||
const { advertisements, loading: adLoading, getActiveAdvertisement, handleAdCtaClick } = useClientAdvertisements();
|
||||
|
||||
const [tierCategories, setTierCategories] = useState([]);
|
||||
const [currentPage, setCurrentPage] = useState(1);
|
||||
const [search, setSearch] = useState("");
|
||||
const [levelFilter, setLevelFilter] = useState("All");
|
||||
const [subFilter, setSubFilter] = useState("All");
|
||||
const [currentPage, setCurrentPage] = useState(1);
|
||||
const [search, setSearch] = useState("");
|
||||
const [levelFilter, setLevelFilter] = useState("All");
|
||||
const [subFilter, setSubFilter] = useState("All");
|
||||
const [categoryFilter, setCategoryFilter] = useState("All");
|
||||
const [modalOpen, setModalOpen] = useState(false);
|
||||
const [modalOpen, setModalOpen] = useState(false);
|
||||
const [selectedCourse, setSelectedCourse] = useState(null);
|
||||
|
||||
const [allCategories, setAllCategories] = useState([]);
|
||||
@@ -179,10 +183,10 @@ const CoursesList = () => {
|
||||
getCourses();
|
||||
api.get("/client/tiers/categories")
|
||||
.then(({ data }) => setTierCategories(data.data ?? []))
|
||||
.catch(() => {});
|
||||
.catch(() => { });
|
||||
api.get("/client/courses/categories")
|
||||
.then(({ data }) => setAllCategories(data.data ?? []))
|
||||
.catch(() => {});
|
||||
.catch(() => { });
|
||||
getActiveAdvertisement("course_list.banner");
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
@@ -199,10 +203,10 @@ const CoursesList = () => {
|
||||
const filtered = useMemo(() =>
|
||||
courses
|
||||
.filter((c) => {
|
||||
const matchSearch = c.title.toLowerCase().includes(search.toLowerCase()) ||
|
||||
const matchSearch = c.title.toLowerCase().includes(search.toLowerCase()) ||
|
||||
(c.description ?? "").toLowerCase().includes(search.toLowerCase());
|
||||
const matchLevel = levelFilter === "All" || (c.level ?? "").toLowerCase() === levelFilter.toLowerCase();
|
||||
const matchSub = subFilter === "All" || c.subscription === subFilter;
|
||||
const matchLevel = levelFilter === "All" || (c.level ?? "").toLowerCase() === levelFilter.toLowerCase();
|
||||
const matchSub = subFilter === "All" || c.subscription === subFilter;
|
||||
const matchCategory = categoryFilter === "All" || (c.categories ?? []).some((cat) => String(cat.id) === categoryFilter);
|
||||
return matchSearch && matchLevel && matchSub && matchCategory;
|
||||
})
|
||||
@@ -211,7 +215,7 @@ const CoursesList = () => {
|
||||
);
|
||||
|
||||
const totalPages = Math.max(1, Math.ceil(filtered.length / ITEMS_PER_PAGE));
|
||||
const paginated = filtered.slice((currentPage - 1) * ITEMS_PER_PAGE, currentPage * ITEMS_PER_PAGE);
|
||||
const paginated = filtered.slice((currentPage - 1) * ITEMS_PER_PAGE, currentPage * ITEMS_PER_PAGE);
|
||||
|
||||
const handleViewDetails = (course) => {
|
||||
if (course.is_locked) {
|
||||
@@ -299,6 +303,25 @@ const CoursesList = () => {
|
||||
<Banner ad={bannerAd} onCtaClick={handleAdCtaClick} />
|
||||
)}
|
||||
|
||||
{categoryFilter !== "All" && (
|
||||
<div className="flex items-center flex-wrap gap-2">
|
||||
<span className="text-sm text-muted-foreground">Tags:</span>
|
||||
{allCategories
|
||||
.filter((cat) => String(cat.id) === categoryFilter)
|
||||
.map((cat) => (
|
||||
<Badge
|
||||
key={cat.id}
|
||||
variant="default"
|
||||
className="cursor-pointer"
|
||||
onClick={() => { setCategoryFilter("All"); setCurrentPage(1); }}
|
||||
>
|
||||
<Tags className="size-3" />
|
||||
{cat.name}
|
||||
</Badge>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Course Grid */}
|
||||
{coursesLoading ? (
|
||||
<div className="xs:pt-12 lg:pt-0 grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-4">
|
||||
|
||||
Reference in New Issue
Block a user