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
198 changes: 128 additions & 70 deletions src/components/Admin.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ import PageHead from "./layout/PageHead";
import PageSection from "./layout/PageSection";
import ResourceEditor from "@/pages/admin/components/ResourceEditor";
import BlogsEditor from "@/pages/admin/components/BlogsEditor";
import Role from "@/pages/admin/components/Role";
import RolesEditor from "@/pages/admin/components/Role";
import FeatureFlags from "@/pages/admin/components/FeatureFlags";

export enum TabValues {
HERO="hero",
Expand All @@ -24,10 +25,131 @@ export enum TabValues {
TEAM="team",
BLOGS = "blogs",
RESOURCES="resources",
ROLES="roles"
ROLES="roles",
FEATURE_FLAGS="feature_flags"

}

const tabComponentMap: Record<TabValues,React.ReactNode> = {
[TabValues.HERO]: (
<TabsContent value={TabValues.HERO} className="mt-0">
<HeroEditor />
</TabsContent>
),
[TabValues.PROJECTS]: (
<TabsContent value={TabValues.PROJECTS} className="mt-0">
<ProjectsEditor />
</TabsContent>
),
[TabValues.ACTIVITIES]: (
<TabsContent value={TabValues.ACTIVITIES} className="mt-0">
<ActivitiesEditor />
</TabsContent>
),
[TabValues.EVENTS]: (
<TabsContent value={TabValues.EVENTS} className="mt-0">
<EventsEditor />
</TabsContent>
),
[TabValues.TEAM]: (
<TabsContent value={TabValues.TEAM} className="mt-0">
<TeamEditor />
</TabsContent>
),
[TabValues.BLOGS]: (
<TabsContent value={TabValues.BLOGS} className="mt-0">
<BlogsEditor />
</TabsContent>
),
[TabValues.RESOURCES]: (
<TabsContent value={TabValues.RESOURCES} className="mt-0">
<ResourceEditor />
</TabsContent>
),
[TabValues.ROLES]: (
<TabsContent value={TabValues.ROLES} className="mt-0">
<RolesEditor />
</TabsContent>
),
[TabValues.FEATURE_FLAGS]: (
<TabsContent value={TabValues.FEATURE_FLAGS} className="mt-0">
<FeatureFlags />
</TabsContent>
),
}

const tabTriggerList: React.ReactNode[] = [
(
<TabsTrigger value={TabValues.HERO} className="flex items-center gap-2">
<Home className="h-4 w-4" /> Hero Section
</TabsTrigger>
),
(
<TabsTrigger value={TabValues.PROJECTS} className="flex items-center gap-2">
<FileText className="h-4 w-4" /> Projects
</TabsTrigger>
),
(
<TabsTrigger value={TabValues.ACTIVITIES} className="flex items-center gap-2">
<FileText className="h-4 w-4" /> Activities
</TabsTrigger>
),
(
<TabsTrigger value={TabValues.EVENTS} className="flex items-center gap-2">
<Calendar className="h-4 w-4" /> Events
</TabsTrigger>
),
(
<TabsTrigger value={TabValues.TEAM} className="flex items-center gap-2">
<Users className="h-4 w-4" /> Team
</TabsTrigger>
),
(
<TabsTrigger value={TabValues.BLOGS} className="flex items-center gap-2">
<Users className="h-4 w-4" /> Blogs
</TabsTrigger>
),
(
<TabsTrigger value={TabValues.RESOURCES} className="flex items-center gap-2">
<Book className="h-4 w-4" /> Resources
</TabsTrigger>
),
(
<TabsTrigger value={TabValues.ROLES} className="flex items-center gap-2">
<Book className="h-4 w-4" /> Roles
</TabsTrigger>
),
(
<TabsTrigger value={TabValues.FEATURE_FLAGS} className="flex items-center gap-2">
<Book className="h-4 w-4" /> Feature Flags
</TabsTrigger>
),
]

const titleMap: Record<TabValues, string> = {
[TabValues.HERO]: "Hero Section Editor",
[TabValues.PROJECTS]: "Projects Editor",
[TabValues.ACTIVITIES]: "Activities Editor",
[TabValues.EVENTS]: "Events Editor",
[TabValues.TEAM]: "Team Members Editor",
[TabValues.BLOGS]: "Blogs Editor",
[TabValues.RESOURCES]: "Add Resources",
[TabValues.ROLES]: "Define Roles",
[TabValues.FEATURE_FLAGS]: "Feature Flags",
}

const descriptionMap: Record<TabValues, string> = {
[TabValues.HERO]:"Edit the main heading, text and background images",
[TabValues.PROJECTS]:"Add, edit or remove projects",
[TabValues.ACTIVITIES]:"Manage robotics activities and workshops",
[TabValues.EVENTS]:"Add or edit upcoming events and competitions",
[TabValues.TEAM]:"Manage team members and their information",
[TabValues.BLOGS]:"Manage blog posts",
[TabValues.RESOURCES]:"Manage Resources and Links",
[TabValues.ROLES]:"Manage Roles for different society members",
[TabValues.FEATURE_FLAGS]: "Manage Enabling and Disabling Features",
}

const Admin = () => {
const [activeTab, setActiveTab] = useState(TabValues.HERO);
return (
Expand All @@ -52,85 +174,21 @@ const Admin = () => {
<Tabs defaultValue={TabValues.HERO} value={activeTab} onValueChange={(value: unknown) => setActiveTab(value as TabValues)} className="w-full mb-12">
<div className="overflow-x-auto pb-2">
<TabsList className="mb-8">
<TabsTrigger value={TabValues.HERO} className="flex items-center gap-2">
<Home className="h-4 w-4" /> Hero Section
</TabsTrigger>
<TabsTrigger value={TabValues.PROJECTS} className="flex items-center gap-2">
<FileText className="h-4 w-4" /> Projects
</TabsTrigger>
<TabsTrigger value={TabValues.ACTIVITIES} className="flex items-center gap-2">
<FileText className="h-4 w-4" /> Activities
</TabsTrigger>
<TabsTrigger value={TabValues.EVENTS} className="flex items-center gap-2">
<Calendar className="h-4 w-4" /> Events
</TabsTrigger>
<TabsTrigger value={TabValues.TEAM} className="flex items-center gap-2">
<Users className="h-4 w-4" /> Team
</TabsTrigger>
<TabsTrigger value={TabValues.BLOGS} className="flex items-center gap-2">
<Users className="h-4 w-4" /> Blogs
</TabsTrigger>
<TabsTrigger value={TabValues.RESOURCES} className="flex items-center gap-2">
<Book className="h-4 w-4" /> Resources
</TabsTrigger>
<TabsTrigger value={TabValues.ROLES} className="flex items-center gap-2">
<Book className="h-4 w-4" /> Roles
</TabsTrigger>
{tabTriggerList}
</TabsList>
</div>

<Card className="shadow-md">
<CardHeader>
<CardTitle>
{activeTab === TabValues.HERO && "Hero Section Editor"}
{activeTab === TabValues.PROJECTS && "Projects Editor"}
{activeTab === TabValues.ACTIVITIES && "Activities Editor"}
{activeTab === TabValues.EVENTS && "Events Editor"}
{activeTab === TabValues.TEAM && "Team Members Editor"}
{activeTab === TabValues.BLOGS && "Blogs Editor"}
{activeTab === TabValues.RESOURCES && "Add Resources"}
{activeTab === TabValues.ROLES && "Define Roles"}
{titleMap[activeTab]}
</CardTitle>
<CardDescription>
{activeTab === TabValues.HERO && "Edit the main heading, text and background images"}
{activeTab === TabValues.PROJECTS && "Add, edit or remove projects"}
{activeTab === TabValues.ACTIVITIES && "Manage robotics activities and workshops"}
{activeTab === TabValues.EVENTS && "Add or edit upcoming events and competitions"}
{activeTab === TabValues.TEAM && "Manage team members and their information"}
{activeTab === TabValues.BLOGS && "Manage blog posts"}
{activeTab === TabValues.RESOURCES && "Manage Resources and Links"}
{activeTab === TabValues.ROLES && "Manage Roles for different society members"}
{descriptionMap[activeTab]}
</CardDescription>
</CardHeader>
<CardContent>
<TabsContent value={TabValues.HERO} className="mt-0">
<HeroEditor />
</TabsContent>

<TabsContent value={TabValues.PROJECTS} className="mt-0">
<ProjectsEditor />
</TabsContent>

<TabsContent value={TabValues.ACTIVITIES} className="mt-0">
<ActivitiesEditor />
</TabsContent>

<TabsContent value={TabValues.EVENTS} className="mt-0">
<EventsEditor />
</TabsContent>

<TabsContent value={TabValues.TEAM} className="mt-0">
<TeamEditor />
</TabsContent>
<TabsContent value={TabValues.BLOGS} className="mt-0">
<BlogsEditor />
</TabsContent>
<TabsContent value={TabValues.RESOURCES} className="mt-0">
<ResourceEditor />
</TabsContent>
<TabsContent value={TabValues.ROLES} className="mt-0">
<Role />
</TabsContent>
{tabComponentMap[activeTab]}
</CardContent>
</Card>
</Tabs>
Expand Down
44 changes: 44 additions & 0 deletions src/components/FeatureDisabled.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { AlertCircle, Clock } from 'lucide-react';

interface ClosedPageCardProps {
title?: string;
message?: string;
showIcon?: boolean;
}

const FeatureDisabled = ({
title = "Applications Closed",
message = "This page is not currently accepting responses. Please check back later.",
showIcon = true,
}: ClosedPageCardProps) => {
return (
<div className="flex items-center justify-center bg-gradient-to-br from-slate-50 to-slate-100 px-4">
<div className="w-full max-w-md bg-white rounded-lg shadow-lg border border-slate-200 p-8">
{showIcon && (
<div className="flex justify-center mb-6">
<div className="p-3 bg-amber-100 rounded-full">
<Clock className="w-8 h-8 text-amber-600" />
</div>
</div>
)}

<h1 className="text-2xl font-bold text-center text-slate-900 mb-3">
{title}
</h1>

<p className="text-center text-slate-600 mb-6 leading-relaxed">
{message}
</p>

<div className="flex items-center justify-center gap-2 p-4 bg-blue-50 rounded-md border border-blue-200">
<AlertCircle className="w-5 h-5 text-blue-600 flex-shrink-0" />
<p className="text-sm text-blue-700">
We'll notify you when responses are accepted again.
</p>
</div>
</div>
</div>
);
}

export default FeatureDisabled;
41 changes: 41 additions & 0 deletions src/lib/supabase/actions/flags.actions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { FeatureFlagType } from "@/types";
import { client } from "../supabase"

export const createFeatureFlag = async (value: Omit<FeatureFlagType, "id" | "created_at" | "updatedAt">) => {
const {error} = await client.from("featureFlags").insert(value);

if(error) {
console.log(error);
return error;
}

return null;
}

export const getFeatureFlags= async (): Promise<FeatureFlagType[]> => {
const {data,error} = await client.from("featureFlags").select("*").order("name", {ascending: true});

if(error) console.log(error);

return (data ?? []) as FeatureFlagType[];
}

export const updateFeatureFlag = async (id: string, isEnabled: boolean) => {
const {error} = await client.from("featureFlags").update({isEnabled}).eq("id", id);

if(error) {
console.log(error);
return error;
}
return null;
}

export const getFeatureFlagByName = async (name: string): Promise<FeatureFlagType | null> => {
const {data,error} = await client.from("featureFlags").select("*").eq("name", name).maybeSingle();

if(error) {
console.log(error);
}

return data as FeatureFlagType;
}
Loading
Loading