Back to Archive
Case Study ยท 2024FeaturedLIVE v1.0

GRID

GRID

A dynamic, full-stack platform for streamlined event, club, and community management.

GRID
Permissions Updated (Instant)

GRID is a comprehensive web application designed to centralize and simplify the complex operations of school or organizational administration. It offers robust tools for managing events, clubs, news, notices, and user permissions, all within a sleek, intuitive interface.

Problem Visual
The Problem

Fragmented Operations & Manual Overload

Educational institutions often struggle with fragmented communication channels, manual processes for event and club management, and an inability to effectively manage user roles and permissions. This leads to administrative bottlenecks, missed opportunities for student engagement, and security vulnerabilities due to inconsistent access controls. The challenge is to consolidate these disparate functions into a cohesive, real-time platform.

Solution Visual
The Solution

Unified Campus Management.
Real-time Control.

GRID addresses these challenges by providing a unified, full-stack solution built on Next.js, React, and Convex. It features an intuitive admin dashboard for complete oversight, dynamic CRUD operations for events, clubs, news, and notices, and a sophisticated Role-Based Access Control (RBAC) system powered by Convex Auth. Real-time updates and a responsive UI ensure efficient operations and a seamless user experience across all modules.

Feature Visual
Implementation

Role-Based Access & Dynamic UI.

Convex Backend
RBAC
Drag-and-Drop UI
Real-time Updates

System Core // Admin Access Control with Convex Auth

import { useQuery, useConvexAuth } from "convex/react";
import { api } from "@/convex/_generated/api";
import { useRouter } from "next/navigation";
import { useEffect, useState } from "react";

export default function AdminLayout({
    children,
}: {
    children: React.ReactNode;
}) {
    const router = useRouter();
    const { isAuthenticated, isLoading } = useConvexAuth();
    const user = useQuery(api.profile.getCurrentUserFromId);
    const [isAuthorized, setIsAuthorized] = useState(false);

    useEffect(() => {
        if (isLoading) return; // Wait for auth to initialize

        if (!isAuthenticated) {
            router.push("/login");
            return;
        }

        if (user) {
            if (user.role === "super_admin" || user.role === "principal") {
                setIsAuthorized(true);
            } else {
                router.push("/"); // Redirect unauthorized users
            }
        } else if (user === null) {
            router.push("/login"); // Authenticated but no profile
        }
    }, [isLoading, isAuthenticated, user, router]);

    if (isLoading || (isAuthenticated && user === undefined) || !isAuthorized) {
        // ... loading state UI
    }

    return (
        // ... main layout with PermissionsProvider
    );
}
typescript
Next Project

Next Case Study

Southside Flow