Skip to content

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

UniVeranstaltungen

UniVeranstaltungen is a university events management platform for creating, publishing, and managing events (bazaars, trips, conferences, workshops, gym sessions) and for handling vendor applications (bazaar participation and booth rentals). The project includes a TypeScript + Express backend and a React + Vite frontend.

Motivation

The German University in Cairo (GUC) hosts numerous events throughout the academic year, including bazaars, workshops, trips, conferences, and sports activities. Managing these events manually via spreadsheets and emails was inefficient and error-prone. This platform was developed to:

  • Centralize event management: Provide a single platform for the Events Office to create, edit, and manage all university events
  • Streamline vendor applications: Allow external vendors to apply for bazaars and booths with an automated review workflow
  • Enhance student engagement: Enable students and staff to browse, register, and receive notifications for upcoming events
  • Implement gamification: Encourage participation through points, badges, streaks, and leaderboards
  • Reduce administrative overhead: Automate email notifications, certificate generation, and payment processing

Build Status

Current Issues / Known Bugs

Issue Status Description
Email verification delay In Progress Verification emails may take up to 2 minutes to arrive during peak hours
Mobile responsiveness In Progress Some dialogs need better mobile viewport handling
Stripe test mode only Planned Payment integration is currently in test mode only
Image upload size Known Large image uploads (>5MB) may timeout on slower connections

Build Information

  • Backend: ✅ Builds successfully with npm run build
  • Frontend: ✅ Builds successfully with npm run build
  • Database: Requires MongoDB (Atlas or local instance)
  • Node Version: Requires Node.js 18+

Code Style

This project follows consistent coding conventions across the codebase:

Naming Conventions

  • Files: PascalCase for React components (EventsList.tsx), camelCase for utilities (authMiddleware.ts)
  • Variables/Functions: camelCase (getUserById, isVerified)
  • Constants: UPPER_SNAKE_CASE (JWT_SECRET, MONGO_URI)
  • Interfaces/Types: PascalCase with I prefix for models (IUser, IEvent)
  • React Components: PascalCase (EventRegistrationDialog, StyledButton)
  • CSS Classes: Tailwind utility classes with consistent ordering

Code Formatting

  • Indentation: 2 spaces
  • Quotes: Double quotes for strings
  • Semicolons: Required
  • TypeScript: Strict mode enabled
  • Linting: ESLint with TypeScript rules

Example Naming

// Interface naming
interface IUser extends Document {
  email: string;
  firstName: string;
  isVerified: boolean;
}

// Function naming
const signUpUser = async (req: Request, res: Response) => { ... }

// Constant naming
const JWT_SECRET = process.env.JWT_SECRET;

// Component naming
export function EventRegistrationDialog({ event, onClose }: Props) { ... }

Screenshots

image image image image image image

Key Features

  • Event management: Create, edit, delete, and archive bazaars, trips, conferences, workshops, and gym sessions
  • Vendor applications: Apply for bazaars and booths with document uploads; admin review workflow with approve/reject actions
  • Role-based access control: Support for Admin, Events Office, Vendor, Student, Staff, TA, and Professor roles
  • JWT authentication: Secure login with email verification and token blacklisting for logout
  • Gamification system: Points, badges, streaks, levels, tiers (Bronze/Silver/Gold), and faculty leaderboards
  • Payment processing: Stripe integration for vendor application fees (test mode)
  • Wallet system: In-app wallet for event registrations and transactions
  • Favorites system: Save and track favorite events across sessions
  • Event registration: Register for workshops, trips, and conferences with QR code tickets
  • Sports court booking: Book and manage university sports court reservations
  • Clubs management: Browse and join university clubs
  • Gallery system: Upload and view event photos
  • Certificate generation: Auto-generate attendance certificates for events
  • Notification system: Real-time notifications for event updates, application status changes
  • Advanced filtering: Filter events by type, status, date, category with sorting options
  • Auto-generated API documentation: Swagger/OpenAPI docs at /api/docs

Tech Stack

Category Technologies
Backend Node.js, Express, TypeScript, Mongoose (MongoDB)
Frontend React 18, TypeScript, Vite
Authentication JWT (jsonwebtoken), bcryptjs
Validation Joi
Email Nodemailer
Payments Stripe
API Docs swagger-jsdoc, swagger-ui-express
Styling Tailwind CSS, Framer Motion
HTTP Client Axios
UI Components Radix UI, Lucide Icons
State Management React Context API

Project Structure

UniVeranstaltungen/
├── server/
│   ├── src/
│   │   ├── config/              # Configuration (database, swagger)
│   │   ├── controllers/         # Route handlers
│   │   ├── middleware/          # Auth & validation middleware
│   │   ├── models/              # Mongoose schemas
│   │   ├── routes/              # Express routes
│   │   ├── scripts/             # Database scripts (resetAndPopulateDB, initializeBooths)
│   │   ├── app.ts               # Express app setup
│   │   └── server.ts            # Server entry point
│   ├── .env                     # Environment variables (not committed)
│   ├── package.json
│   └── tsconfig.json
├── client/
│   ├── src/
│   │   ├── components/          # React components (ui, common, admin, events, vendor, workshops)
│   │   ├── services/            # API service clients
│   │   ├── types/               # TypeScript type definitions
│   │   ├── utils/               # Utility functions
│   │   ├── hooks/               # Custom React hooks
│   │   ├── data/                # Mock JSON data
│   │   ├── styles/              # Global styles
│   │   ├── App.tsx              # Main App component
│   │   └── main.tsx             # React entry point
│   ├── public/                  # Static assets
│   ├── .env                     # Environment variables (not committed)
│   ├── package.json
│   ├── vite.config.ts
│   └── tsconfig.json
├── client/guidelines/           # Design system & implementation guidelines
├── client/audit-fixes/          # Audit documentation and fixes
└── README.md

Quick Start (Development)

Prerequisites:

  • Node.js 18+
  • MongoDB (Atlas or local)

1. Backend Setup

cd server
npm install
# create .env (see Environment Variables below)
npm run dev

Server default: http://localhost:4000

Important for local MongoDB: Before running the development server, initialize the database:

npm run db:reset

This script will:

  • Drop all existing collections
  • Create sample users (admin, professor, staff, students, etc.)
  • Populate test data (bazaars, trips, conferences, workshops, booths, etc.)
  • Initialize all database indexes

2. Frontend Setup

cd client
npm install
# create .env (see .env.example)
npm run dev

Frontend default: http://localhost:3000

3. API Documentation

Open Swagger UI: http://localhost:4000/api/docs

Environment Variables

Backend (server/.env)

Example:

PORT=4000
MONGO_URI=mongodb+srv://<user>:<pass>@cluster.mongodb.net/<db>
MONGO_DB=<db name>
JWT_SECRET=your-32+ char secret
EMAIL_SERVICE=Gmail
EMAIL_USER=stodgytomcat561@gmail.com
EMAIL_PASS=pass
MAIL_FROM=stodgytomcat561@gmail.com
CLIENT_URL=http://localhost:3000
AbstractAPIKey=your_api_key

Frontend (client/.env)

See client/.env.example for required variables.

⚠️ Do not commit .env files to version control.

API Endpoints (summary)

Authentication

  • POST /api/auth/register
  • POST /api/auth/login
  • GET /api/auth/verify/:token

Events

  • GET /api/upcoming-events
  • GET /api/search-events

Event Management (Events Office)

  • POST /api/events/bazaars
  • POST /api/events/trips
  • POST /api/events/conferences
  • POST /api/events/gym-sessions
  • PATCH /api/events/{type}/{id}
  • DELETE /api/events/{type}/{id}

Vendor Applications

  • GET /api/vendors/bazaars — View upcoming bazaars
  • POST /api/vendors/applications/bazaar — Apply for a bazaar
  • POST /api/vendors/applications/booth — Apply for a booth
  • GET /api/vendors/applications/accepted — Approved applications for an email
  • GET /api/vendors/applications/pending-rejected — Pending & rejected applications for an email
  • GET /api/vendors/my-applications — Vendor dashboard applications with filters (email, status, type, includePast)
  • GET /api/vendors/event/:eventId — Vendors for a specific event

Admin

  • GET /api/admin/applications
  • PATCH /api/admin/applications/bazaar/:id/status
  • PATCH /api/admin/applications/booth/:id/status

Health

  • GET /api/health

Available Scripts

Backend (server/)

  • npm run dev — Start dev server with auto-reload
  • npm run db:reset — Reset database and populate with sample data
  • npm run build — Build TypeScript to JavaScript
  • npm start — Start production server

Frontend (client/)

  • npm run dev — Start Vite dev server
  • npm run build — Build for production
  • npm run preview — Preview production build

Code Examples

1. JWT Authentication Middleware

// server/src/middleware/authMiddleware.ts
export const requiresAuth = async (req: AuthRequest, res: Response, next: NextFunction) => {
    const authHeader = req.headers.authorization;

    if (!authHeader || !authHeader.startsWith('Bearer ')) {
        return res.status(401).json({ message: 'Authorization token required' });
    }

    const token = authHeader.split(' ')[1];

    try {
        // Check if the token has been blacklisted
        const isBlacklisted = await BlacklistedToken.findOne({ token });
        if (isBlacklisted) {
            return res.status(401).json({ message: 'Token is invalid (logged out)' });
        }

        const decoded = jwt.verify(token, process.env.JWT_SECRET!);
        req.user = decoded.user;
        next();
    } catch (error) {
        res.status(401).json({ message: 'Invalid or expired token' });
    }
};

2. User Schema with Gamification Fields

// server/src/models/User.ts
export interface IUser extends Document {
  email: string;
  password: string;
  firstName: string;
  lastName: string;
  gucId: string;
  role: "student" | "staff" | "ta" | "professor" | "events_officer" | "admin";
  isVerified: boolean;
  
  // Gamification fields
  gamificationPoints: number;  // Permanent total points earned
  spendablePoints: number;     // Points that can be spent on rewards
  level: number;               // 1-100 (calculated from points)
  tier: 'bronze' | 'silver' | 'gold';
  currentStreak: number;       // Consecutive events attended
  badges: string[];            // Array of unlocked badge IDs
}

3. Joi Validation Schema for User Registration

// server/src/controllers/authController.ts
const userSchema = Joi.object({
  email: Joi.string()
    .trim()
    .email()
    .required()
    .regex(/^[a-zA-Z0-9-]+\.[a-zA-Z0-9-]+@(student\.)?guc\.edu\.eg$/)
    .messages({
      "string.pattern.base":
        "Email must be in the format firstname.lastname@guc.edu.eg",
    }),
  password: Joi.string().trim().min(6).required(),
  firstName: Joi.string().trim().required(),
  lastName: Joi.string().trim().required(),
  gucId: Joi.string().trim().required(),
  role: Joi.string().valid("student", "staff", "ta", "professor").required(),
});

4. React Custom Hook for Event Filtering

// client/hooks/useEventFilterSections.ts
export function useEventFilterSections(
  filters: EventFilters,
  updateFilters: (updates: Partial<EventFilters>) => void
) {
  return useMemo(() => [
    {
      id: 'type',
      title: 'Event Types',
      type: 'radio' as const,
      selectedValues: filters.type ? [filters.type] : [''],
      onChange: (values: string[]) =>
        updateFilters({ type: values[0] || undefined }),
      options: [
        { id: '', label: 'All Events' },
        { id: 'workshop', label: 'Workshops' },
        { id: 'conference', label: 'Conferences' },
        { id: 'bazaar', label: 'Bazaars' },
        { id: 'trip', label: 'Trips' },
      ]
    },
    // ... more filter sections
  ], [filters, updateFilters]);
}

5. Event Status Helper Function

// client/components/events/EventsList.tsx
function getEventStatus(
  startDate: string,
  endDate: string,
  registrationDeadline?: string
): "open" | "upcoming" | "ongoing" | "completed" {
  const now = new Date();
  const eventStart = new Date(startDate);
  const eventEnd = new Date(endDate);

  if (now > eventEnd) return "completed";
  if (now >= eventStart && now <= eventEnd) return "ongoing";

  if (registrationDeadline) {
    const regDeadline = new Date(registrationDeadline);
    regDeadline.setHours(23, 59, 59, 999);
    if (now <= regDeadline) return "open";
  }
  
  return "upcoming";
}

Tests

image image image image image

Suggested Test Cases

Test # Endpoint Method Description Expected Result
1 /api/auth/signup/user POST Register new student 200 OK with JWT token
2 /api/auth/login POST Login with valid credentials 200 OK with JWT token
3 /api/auth/login POST Login with invalid password 401 Unauthorized
4 /api/upcoming-events GET Fetch upcoming events 200 OK with events array
5 /api/vendors/applications/bazaar POST Submit bazaar application (authenticated) 201 Created
6 /api/admin/applications GET Fetch all applications (admin only) 200 OK with applications
7 /api/health GET Health check endpoint 200 OK

Contributing

We welcome contributions to UniVeranstaltungen! Here's how you can help:

Getting Started

  1. Fork the repository on GitHub
  2. Clone your fork locally:
    git clone https://github.com/your-username/UniVeranstaltungen.git
  3. Create a feature branch:
    git checkout -b feature/your-feature-name

Development Guidelines

  • Use TypeScript for all new code (both frontend and backend)
  • Follow existing patterns for naming conventions and code structure
  • Write meaningful commit messages following conventional commits format
  • Test your changes before submitting a PR
  • Update documentation if you add new features or change existing behavior

Pull Request Process

  1. Ensure your code compiles without errors (npm run build)
  2. Update the README.md if needed
  3. Create a Pull Request with a clear title and description
  4. Link any related issues in the PR description
  5. Wait for code review and address any feedback

Code Review Checklist

  • Code follows the existing style guide
  • TypeScript types are properly defined
  • No console.log statements in production code
  • Environment variables are not hardcoded
  • New endpoints are documented with Swagger annotations

Reporting Issues

  • Use GitHub Issues to report bugs
  • Include steps to reproduce the issue
  • Provide environment details (OS, Node version, browser)
  • Attach relevant error messages or screenshots

Credits

https://react.dev/learn https://stackoverflow.com/

Resources & Documentation

Libraries & Frameworks

License

This project is licensed under the MIT License.

Third-Party Licenses

This project uses the following third-party services and libraries that have their own licenses:

See individual package LICENSE files in node_modules for complete license information.


Made with ❤️ for the German University in Cairo

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages