Student Details (परीक्षार्थी विवरण)
Select class (Nursery to 12th / ENG) to auto-load timetable
Saved Students List (Click to Load)
प्रवेश पत्र • Admit Card
Tayeba Khatoon • Roll: 05 • Class 7
SHREE PRATAP NARAYAN INTERMEDIATE COLLEGE
Bansgaon Jamuan, Dudahi-Kushinagar (UP)
| विषय | दिनांक व समय | विषय | दिनांक व समय |
|---|
(M) = Morning (8.00 am to 11.15 am) (E) = Evening (2.00 pm to 5.15 pm)
TAYEBA KHATOON
Roll No: 05 • DOB: 01/01/2016
Father: JAHIR ALI • Mother: JALEKHA KHATOON
परीक्षा समय-सारणी (Exam Schedule) Class 7
Class-Wise Subject & Exam Timetable (Nursery to 12th + English Medium)
Select any class (like LKG, LKG ENG, Class 7, Class 10 ENG) to customize & save its subjects.
Subjects are paired 2-per-row on the Admit Card Board Sheet
| # | Subject Name (विषय) | Exam Date (दिनांक) | Shift (समय) | Board Sheet Position | Actions |
|---|
Saved Students List View (परीक्षार्थी सूची)
Search students by Name, Father's Name, Roll No, or Class. Click Load Admit Card to preview or print immediately.
| Student Photo & Name | Class (Admit Card Label) | Roll No | Father & Mother Name | DOB (DD/MM/YYYY) | Actions |
|---|
School Settings, Shift Timings & Principal Signature
Customize School Name, Academic Year, Morning `(M)` & Evening `(E)` Shift Times, Logo, and Principal Signature.
Complete Supabase SQL Schema, `.env` File & Cloudinary Edge Function
Copy or download the files below to connect your own Supabase project and Cloudinary account via Supabase Edge Functions.
1 Environment Variables (`.env` & Supabase Secrets)
# ============================================================================ # 1. FRONTEND ENVIRONMENT VARIABLES (.env / .env.local) # ============================================================================ VITE_SUPABASE_URL="https://your-project-ref.supabase.co" VITE_SUPABASE_ANON_KEY="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...your-anon-key" VITE_SUPABASE_EDGE_FUNCTION_URL="https://your-project-ref.supabase.co/functions/v1/upload-cloudinary" # ============================================================================ # 2. SUPABASE EDGE FUNCTION SECRETS (Set via CLI for Cloudinary Upload) # Run: supabase secrets set CLOUDINARY_CLOUD_NAME=... CLOUDINARY_API_KEY=... CLOUDINARY_API_SECRET=... # ============================================================================ CLOUDINARY_CLOUD_NAME="your_cloudinary_cloud_name" CLOUDINARY_API_KEY="123456789012345" CLOUDINARY_API_SECRET="your_cloudinary_api_secret" CLOUDINARY_UPLOAD_FOLDER="school_admit_cards"
2 Full Supabase SQL Database Schema & RLS (`supabase_schema.sql`)
-- ============================================================================ -- COMPLETE SUPABASE SQL SCHEMA FOR MULTI-SCHOOL ADMIT CARD GENERATOR PORTAL -- Supports Nursery to 12th (Hindi & English Medium), Editable Shift Timings & Signatures -- ============================================================================ create extension if not exists "pgcrypto"; -- 1. SCHOOLS SETTINGS TABLE (1 row per logged-in school user) create table if not exists public.schools ( id uuid primary key default gen_random_uuid(), user_id uuid not null references auth.users(id) on delete cascade unique, school_name text not null default 'SHREE PRATAP NARAYAN INTERMEDIATE COLLEGE', school_address text not null default 'Bansgaon Jamuan, Dudahi-Kushinagar (UP)', district text not null default 'कुशीनगर', exam_center text not null default 'SHREE PRATAP NARAYAN INTERMEDIATE COLLEGE', academic_year text not null default '2026 - 2027', morning_shift_time text not null default '8.00 am to 11.15 am', evening_shift_time text not null default '2.00 pm to 5.15 pm', instructions text not null default '1. प्रधानाचार्य अपने समक्ष परीक्षार्थी का हस्ताक्षर कराकर स्वयं हस्ताक्षर एवं मुहर अंकित कर परीक्षार्थी को वितरित करें। 2. परीक्षार्थी को परीक्षा के समय इस प्रवेश पत्र को परीक्षा कक्ष में प्रतिदिन लाना अनिवार्य होगा। 3. यह प्रवेश पत्र अहस्तान्तरणीय है। परीक्षार्थी का शैक्षिक विवरण एवं अर्हता आदि से सम्बन्धित प्रपत्र फर्जी पाये जाने पर अथवा तथ्यगोपन कर विनियम विरुद्ध परीक्षा में सम्मिलित होने या जांचोपरान्त परीक्षार्थी का परीक्षाफल/परीक्षाफल किसी भी स्तर पर परिषद द्वारा निरस्त कर दिया जायेगा।', logo_url text, signature_url text, created_at timestamptz not null default now(), updated_at timestamptz not null default now() ); -- 2. CLASS TIMETABLES TABLE (Stores subject list JSONB per class for each school) create table if not exists public.class_timetables ( id uuid primary key default gen_random_uuid(), user_id uuid not null references auth.users(id) on delete cascade, class_name text not null, -- e.g. 'NURSERY', 'LKG', 'LKG ENG', 'UKG ENG', 'Class 7', 'Class 12 ENG' subjects jsonb not null default '[]'::jsonb, updated_at timestamptz not null default now(), unique(user_id, class_name) ); -- 3. STUDENTS ADMIT CARD TABLE create table if not exists public.students ( id uuid primary key default gen_random_uuid(), user_id uuid not null references auth.users(id) on delete cascade, student_name text not null, father_name text not null, mother_name text not null, class_name text not null, roll_number text default '', dob date, category text not null default 'REGULAR', photo_url text, show_roll_in_box boolean not null default false, created_at timestamptz not null default now(), updated_at timestamptz not null default now() ); -- 4. ROW LEVEL SECURITY (RLS) POLICIES alter table public.schools enable row level security; alter table public.class_timetables enable row level security; alter table public.students enable row level security; drop policy if exists "Schools manage own profile" on public.schools; create policy "Schools manage own profile" on public.schools for all using (auth.uid() = user_id) with check (auth.uid() = user_id); drop policy if exists "Schools manage own class timetables" on public.class_timetables; create policy "Schools manage own class timetables" on public.class_timetables for all using (auth.uid() = user_id) with check (auth.uid() = user_id); drop policy if exists "Schools manage own students" on public.students; create policy "Schools manage own students" on public.students for all using (auth.uid() = user_id) with check (auth.uid() = user_id);
3 Supabase Edge Function (`supabase/functions/upload-cloudinary/index.ts`)
// SUPABASE EDGE FUNCTION: upload-cloudinary
// Deploy command: supabase functions deploy upload-cloudinary
import { serve } from "https://deno.land/std@0.177.0/http/server.ts";
const corsHeaders = {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Headers": "authorization, x-client-info, apikey, content-type",
"Access-Control-Allow-Methods": "POST, OPTIONS",
};
async function sha1Hex(message: string): Promise {
const msgUint8 = new TextEncoder().encode(message);
const hashBuffer = await crypto.subtle.digest("SHA-1", msgUint8);
const hashArray = Array.from(new Uint8Array(hashBuffer));
return hashArray.map((b) => b.toString(16).padStart(2, "0")).join("");
}
serve(async (req: Request) => {
if (req.method === "OPTIONS") {
return new Response("ok", { headers: corsHeaders });
}
try {
const CLOUD_NAME = Deno.env.get("CLOUDINARY_CLOUD_NAME");
const API_KEY = Deno.env.get("CLOUDINARY_API_KEY");
const API_SECRET = Deno.env.get("CLOUDINARY_API_SECRET");
const FOLDER = Deno.env.get("CLOUDINARY_UPLOAD_FOLDER") || "school_admit_cards";
if (!CLOUD_NAME || !API_KEY || !API_SECRET) {
throw new Error("Missing Cloudinary environment secrets in Supabase Edge Function.");
}
const { fileBase64, assetType } = await req.json();
if (!fileBase64) throw new Error("fileBase64 is required");
const timestamp = Math.floor(Date.now() / 1000).toString();
const uploadFolder = `${FOLDER}/${assetType || "general"}`;
const paramsToSign = `folder=${uploadFolder}×tamp=${timestamp}${API_SECRET}`;
const signature = await sha1Hex(paramsToSign);
const formData = new FormData();
formData.append("file", fileBase64);
formData.append("api_key", API_KEY);
formData.append("timestamp", timestamp);
formData.append("folder", uploadFolder);
formData.append("signature", signature);
const cloudinaryRes = await fetch(
`https://api.cloudinary.com/v1_1/${CLOUD_NAME}/image/upload`,
{ method: "POST", body: formData }
);
const data = await cloudinaryRes.json();
if (!cloudinaryRes.ok) throw new Error(data.error?.message || "Cloudinary upload failed");
return new Response(
JSON.stringify({ success: true, secure_url: data.secure_url, public_id: data.public_id }),
{ headers: { ...corsHeaders, "Content-Type": "application/json" }, status: 200 }
);
} catch (err: any) {
return new Response(
JSON.stringify({ success: false, error: err.message }),
{ headers: { ...corsHeaders, "Content-Type": "application/json" }, status: 400 }
);
}
});