diff --git a/src/modules/admin/pages/tiers/PlanPolicy.jsx b/src/modules/admin/pages/tiers/PlanPolicy.jsx
deleted file mode 100644
index 03afe7b..0000000
--- a/src/modules/admin/pages/tiers/PlanPolicy.jsx
+++ /dev/null
@@ -1,298 +0,0 @@
-import { useEffect, useState } from "react";
-import { useNavigate, useParams } from "react-router-dom";
-import { ArrowLeft, House, ShieldCheck, Plus, Trash2 } from "lucide-react";
-import { Button } from "@/components/ui/button";
-import { Badge } from "@/components/ui/badge";
-import { Separator } from "@/components/ui/separator";
-import { Skeleton } from "@/components/ui/skeleton";
-import {
- Select, SelectContent, SelectItem, SelectTrigger, SelectValue,
-} from "@/components/ui/select";
-import AppBreadcrumb from "@/components/generic/Breadcrumb/AppBreadcrumb";
-import { PageMeta } from "@/contexts/MetadataContext";
-import { AdminTierPoliciesProvider, useAdminTierPolicies } from "@/contexts/AdminTierPoliciesContext";
-import { useTiers } from "@/contexts/AdminTiersContext";
-import api from "@/utils/api.util";
-
-// ─── Rule type definitions ────────────────────────────────────────────────────
-
-const RULE_DEFS = {
- course_subscription_access: {
- label: "Course Subscription Access",
- description: "Which course subscription levels this plan can unlock.",
- default: { type: "course_subscription_access", levels: ["free"] },
- },
- required_active_tier: {
- label: "Required Active Tier",
- description: "User's tier must be at least this rank to access content.",
- default: { type: "required_active_tier", tier: "" },
- },
- group_restriction: {
- label: "Group Restriction",
- description: "Only users in selected groups can access content.",
- default: { type: "group_restriction", group_ids: [] },
- },
-};
-
-// ─── Rule Editors ─────────────────────────────────────────────────────────────
-
-function CourseAccessEditor({ rule, onChange }) {
- const [availableLevels, setAvailableLevels] = useState(["free"]);
-
- useEffect(() => {
- api.get("/admin/tiers/categories")
- .then(({ data }) => {
- setAvailableLevels((data.data ?? []).filter((c) => c.is_active).map((c) => c.slug));
- })
- .catch(() => {});
- }, []);
-
- const toggle = (level) => {
- const levels = rule.levels ?? [];
- onChange({ ...rule, levels: levels.includes(level) ? levels.filter((l) => l !== level) : [...levels, level] });
- };
-
- return (
-
- {availableLevels.map((lvl) => (
-
- ))}
-
- );
-}
-
-function RequiredTierEditor({ rule, onChange }) {
- const [categories, setCategories] = useState([]);
-
- useEffect(() => {
- api.get("/admin/tiers/categories")
- .then(({ data }) => setCategories((data.data ?? []).filter((c) => c.is_active && !c.is_default)))
- .catch(() => {});
- }, []);
-
- return (
-
- );
-}
-
-function GroupRestrictionEditor({ rule, onChange }) {
- const [groups, setGroups] = useState([]);
-
- useEffect(() => {
- api.get("/admin/groups").then(({ data }) => setGroups(data.data?.data ?? [])).catch(() => {});
- }, []);
-
- const toggleGroup = (gid) => {
- const ids = rule.group_ids ?? [];
- onChange({ ...rule, group_ids: ids.includes(gid) ? ids.filter((id) => id !== gid) : [...ids, gid] });
- };
-
- return (
-
- {groups.length === 0 &&
No groups found.
}
- {groups.map((g) => {
- const selected = (rule.group_ids ?? []).includes(Number(g.group_id));
- return (
-
- );
- })}
-
- );
-}
-
-function RuleCard({ rule, index, onChange, onRemove }) {
- const def = RULE_DEFS[rule.type];
- return (
-
-
-
-
{def?.label ?? rule.type}
-
{def?.description}
-
-
-
- {rule.type === "course_subscription_access" &&
onChange(index, r)} />}
- {rule.type === "required_active_tier" && onChange(index, r)} />}
- {rule.type === "group_restriction" && onChange(index, r)} />}
-
- );
-}
-
-function SectionCard({ icon: Icon, title, children }) {
- return (
-
-
- {Icon && }
-
{title}
-
-
- {children}
-
- );
-}
-
-// ─── Inner page ───────────────────────────────────────────────────────────────
-
-function PlanPolicyInner() {
- const navigate = useNavigate();
- const { planId } = useParams();
- const { fetchPlan, plan, loading: planLoading } = useTiers();
- const { fetchPlanPolicy, savePlanPolicy, policy, loading } = useAdminTierPolicies();
-
- const [rules, setRules] = useState([]);
-
- useEffect(() => {
- fetchPlan(planId);
- fetchPlanPolicy(planId);
- }, [planId]);
-
- useEffect(() => {
- if (policy) setRules(policy.access_rules ?? []);
- }, [policy]);
-
- const handleRuleChange = (index, updated) =>
- setRules((prev) => prev.map((r, i) => (i === index ? updated : r)));
-
- const removeRule = (index) =>
- setRules((prev) => prev.filter((_, i) => i !== index));
-
- const addRule = (type) => {
- const def = RULE_DEFS[type];
- if (!def) return;
- setRules((prev) => [...prev, { ...def.default }]);
- };
-
- const usedTypes = new Set(rules.map((r) => r.type));
-
- const handleSave = async () => {
- await savePlanPolicy(planId, { access_rules: rules });
- };
-
- return (
-
-
-
-
-
-
-
, to: "/admin" },
- { label: "Plans", to: "/admin/tiers/plans" },
- { label: plan?.label ?? `Plan #${planId}`, to: `/admin/tiers/plans/${planId}/view` },
- { label: "Policy" },
- ]} />
-
-
-
-
-
-
-
Access Policy
-
- {planLoading ? : (plan?.label ?? `Plan #${planId}`)}
-
-
-
-
-
-
-
-
-
- {rules.length === 0 && (
-
- No rules defined. Content access falls back to tier rank comparison.
-
- )}
-
-
- {rules.map((rule, i) => (
- removeRule(i)}
- />
- ))}
-
-
-
-
Add Rule
-
- {Object.entries(RULE_DEFS).map(([type, def]) => (
-
- ))}
-
-
-
-
- {plan && (
-
- {plan.tier}
- {plan.label}
- ·
- {plan.duration_days} days
-
- )}
-
-
-
-
-
- );
-}
-
-export default function PlanPolicy() {
- return (
-
-
-
- );
-}
diff --git a/src/modules/admin/pages/tiers/ViewPlan.jsx b/src/modules/admin/pages/tiers/ViewPlan.jsx
index 5af2e7b..e443349 100644
--- a/src/modules/admin/pages/tiers/ViewPlan.jsx
+++ b/src/modules/admin/pages/tiers/ViewPlan.jsx
@@ -1,6 +1,6 @@
import { useEffect, useState, useMemo } from "react";
import { useNavigate, useParams } from "react-router-dom";
-import { ArrowLeft, House, Pencil, Tag, BadgeCheck, ShieldCheck } from "lucide-react";
+import { ArrowLeft, House, Pencil, Tag, BadgeCheck } from "lucide-react";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import { Skeleton } from "@/components/ui/skeleton";
@@ -86,15 +86,6 @@ export default function ViewPlan() {
-