0%
balqalam Logo
balqalam
FeaturesCommunityPricingDocumentation
Login
  • Introduction
  • Pitch
  • Hogwarts
  • Live Demo
  • MVP
  • Roadmap
  • Launch Sprint
  • PRD
  • Get Started
  • Localhost
  • Architecture
  • Structure
  • Pattern
  • Page
  • Layout
  • Content
  • Types
  • Config
  • Actions
  • Queries
  • Authorization
  • Validation
  • Form
  • Table
  • Detail
  • Card
  • Util
  • Hooks
  • List Params
  • Views
  • README.md
  • ISSUE.md
  • Technology Stack
  • Database
  • File
  • CDN Assets
  • Entry Points
  • Dashboard
  • Authentication
  • Credentials
  • OAuth
  • Flow Diagrams
  • Multi-Tenancy
  • Offline
  • Onboarding
  • Onboarding Videos
  • Add Values
  • Admission
  • Application
  • Attendance
  • Compliance
  • Profile
  • Exams
  • Exam Wizard
  • Timetable
  • Classrooms
  • Notifications
  • Conference
  • LMS (Lumos)
Finance
  • Finance
  • Fee Management
  • Invoice
  • Wallet
  • Salary
  • Payroll
  • Timesheet
  • Expenses
  • Budget
  • Receipt
  • Accounts
  • Banking
  • Reports
  • Dashboard
  • Permissions
  • Messages
  • Integration Flow
  • Provision
  • AI Document Processing
  • Document Intelligence
  • Internationalization
  • Translation
  • Translation Guide
  • Icons
  • Docs Factory
  • Inspiration
  • Listings
  • Teachers
  • Students
  • Catalog
  • Library
  • Contributing
  • Code of conduct
  • GitHub Workflow
  • Database Seeds
  • Database Safety
  • Test Accounts
  • Playwright
  • Prettier
  • Block Rebound
Sales & GTM
  • Marketing Brief
  • Sales
  • Go-to-market
  • Marketing
  • Admission — Feature Spotlight
  • Pilot Program
  • Leads
  • Proposal
  • Outreach Templates
  • Case Study
  • Competitors
  • Landing-page teardown
  • Competitor FAQ
  • Business model
  • Shared economy
  • Traction
Fundraising & Ecosystem
  • Get Support
  • Investor Deck
  • Data Room
  • Investors
  • Accelerators
  • Incubators
  • Grants
  • Sponsors
  • Partners
  • Competitions & Hackathons
  • Universities & Training Centers

File

PreviousNext

Centralized file operations — upload, browse, export, import, print, and document generation.

The @/components/file module consolidates every file-related concern into one place. Six sub-modules, one import surface.

Sub-modulePurpose
UploadCloud-based file upload with drag-and-drop and progress tracking
BrowserFile manager UI with grid / list views
ExportGenerate PDF, Excel, CSV, JSON from data
ImportParse CSV / Excel with a validation wizard
PrintBrowser-native print and print-to-PDF
GenerateTemplated documents — invoice, receipt, certificate, report card, ID card, transcript

Quick start

import {
  Uploader,
  ExportButton,
  Importer,
  PrintButton,
  FileBrowser,
  useUpload,
  useExport,
  useGenerate,
} from "@/components/file"
 
<Uploader folder="documents" category="document" onUpload={(urls) => console.log(urls)} />
 
<ExportButton
  data={students}
  config={{ columns: STUDENT_EXPORT_COLUMNS, filename: "students" }}
  formats={["csv", "excel", "pdf"]}
/>
 
<Importer columns={STUDENT_IMPORT_COLUMNS} onImport={handleImport} />
 
<PrintButton contentRef={printRef}>Print Report</PrintButton>
 
<FileBrowser rootFolder="/school/documents" onSelect={handleSelect} />

Upload

The Uploader component renders a drag-and-drop dropzone backed by S3 signed URLs.

<Uploader
  folder="avatars"
  category="image"
  accept={{ "image/*": [".jpg", ".png", ".webp"] }}
  maxSize={5 * 1024 * 1024}
  maxFiles={1}
  onUpload={(urls) => setAvatarUrl(urls[0])}
  onError={(error) => toast.error(error)}
/>

Presets

Ready-to-use configurations live alongside the Uploader: AvatarUploader, DocumentUploader, ImageUploader, VideoUploader. Each presets accept, maxSize, and category for the common shapes. Read source for exact props.

useUpload hook

The hook exposes the same upload pipeline imperatively (no UI), useful for custom triggers.

const { upload, progress, isUploading, error } = useUpload({
  folder: "documents",
  category: "document",
})
 
await upload(file) // returns the public URL

Server actions

Two actions back the module:

ActionPurpose
getSignedUrl()Mint a presigned PUT URL for the client to upload to S3.
confirmUpload()Persist the resulting FileObject row keyed by schoolId.

Both validate auth() + getTenantContext() and write schoolId into every record.

Export

ExportButton opens a format picker (CSV, Excel, PDF, JSON) and triggers download.

<ExportButton
  data={students}
  config={{
    columns: STUDENT_EXPORT_COLUMNS,
    filename: "students",
    title: "Student Roster",
  }}
  formats={["csv", "excel", "pdf"]}
/>

For inline use without a picker, SimpleExportButton accepts a single format.

useExport hook

const { exportData, isExporting } = useExport()
 
await exportData({
  format: "pdf",
  data: students,
  config: { columns: STUDENT_EXPORT_COLUMNS, filename: "students" },
})

Columns

Per-feature column definitions live alongside the feature (e.g. students/columns-export.ts). They build on createColumn(key, label, options) helpers from @/components/file/export/columns. Common options: format, width, align, accessor.

Import

Importer renders a four-step wizard: upload → preview → map columns → validate.

<Importer
  columns={STUDENT_IMPORT_COLUMNS}
  template={{ filename: "students-template.xlsx", sheets: ["Students"] }}
  onImport={async (rows) => {
    const result = await bulkImportStudents(rows)
    toast.success(`Imported ${result.created} of ${rows.length}`)
  }}
/>

useImport hook

const { parse, validate, isImporting } = useImport()
 
const rows = await parse(file)
const issues = await validate(rows, columns)

Validation

validateRow(row, columns) checks every column's required, type, and custom validate(value, row). validateBatch(rows, columns) returns a per-row issue list and a totals summary.

Print

PrintButton opens the browser print dialog scoped to a content ref.

const printRef = useRef<HTMLDivElement>(null)
 
<PrintButton contentRef={printRef} title="Student Report">
  Print
</PrintButton>
 
<div ref={printRef}>{/* printable content */}</div>

usePrint hook

const { print } = usePrint()
print(printRef.current, { title: "Student Report" })

Generate

Pre-built templates render PDFs via @react-pdf/renderer. All return a Blob and a download trigger.

TemplateHelperUse
InvoiceuseGenerate.invoice()Fee invoices, receipts
ReceiptuseGenerate.receipt()Payment confirmation
CertificateuseGenerate.certificate()Course or achievement certificates
Report carduseGenerate.reportCard()Term and annual reports
ID carduseGenerate.idCard()Student / staff badges
TranscriptuseGenerate.transcript()Academic transcripts
const { invoice } = useGenerate()
const blob = await invoice({ schoolId, items, customer, total })

Each template accepts a typed payload and renders both a downloadable PDF and an inline preview component (InvoicePreview, etc.).

Browser

FileBrowser renders a tree-aware file manager rooted at any S3 prefix.

<FileBrowser
  rootFolder={`/${schoolId}/documents`}
  onSelect={(file) => setSelected(file)}
  view="grid"
/>

useBrowser hook

const { files, currentFolder, navigate, search } = useBrowser({
  rootFolder: `/${schoolId}/documents`,
})

Storage and limits

ConstraintDefault
ProviderAWS S3 + CloudFront CDN
Default size cap10 MB per file (per category override)
Image cap5 MB
Document cap25 MB
Video cap100 MB
Allowed typesPer-category whitelist; rejected uploads return error code

Multi-tenant safety

Every persisted file row carries schoolId. Signed URLs include a schoolId claim so cross-tenant URL forging is impossible. FileBrowser always rooted at a schoolId-scoped prefix.

// correct — schoolId scope on every query
await db.fileObject.findMany({ where: { schoolId, folder } })

i18n

UI text comes from the dictionary.file slice. Helpers (getDictionary server-side, useI18nMessages on the client) provide the full set of labels for the picker, the wizard, error toasts, and progress states.

Errors

Server actions return error codes; the client maps them via useI18nMessages(dictionary).error.

CodeMeaning
FILE_TOO_LARGEExceeds the per-category size cap
INVALID_FILE_TYPEMIME type not in the category whitelist
UPLOAD_FAILEDS3 returned non-2xx
MISSING_TENANTNo schoolId on the session
UNAUTHORIZEDauth() check failed
INVALID_FOLDERFolder path outside the schoolId-scoped tree

TypeScript

All public exports are fully typed. Common types:

import type {
  ExportConfig,
  FileObject,
  GenerateConfig,
  ImportConfig,
  PrintConfig,
  UploadConfig,
} from "@/components/file"

Migration from the old layout

Older code imported from @/components/upload, @/components/export, @/components/import, etc. Migrate to a single import:

// before
import { ExportButton } from "@/components/export"
// after
import { ExportButton, Uploader } from "@/components/file"
import { Uploader } from "@/components/upload"

The old module paths still re-export for compatibility but are deprecated. Open issues for any direct imports still in the wild.

DatabaseCDN Assets

On This Page

Quick startUploadPresetsuseUpload hookServer actionsExportuseExport hookColumnsImportuseImport hookValidationPrintusePrint hookGenerateBrowseruseBrowser hookStorage and limitsMulti-tenant safetyi18nErrorsTypeScriptMigration from the old layout

Built by Databayt ·

Welcome to balqalam.

A great journey is about to begin.