Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
3a4bf10
feat(azure-deploy): add workflow for deploying backend to Azure Web App
yehiarasheed Dec 18, 2025
c8f97c5
Update branch name for Azure deployment workflow
yehiarasheed Dec 18, 2025
e053c55
chore: add consola to dependencies for Azure
yehiarasheed Dec 18, 2025
637017a
fix: update Node.js version for Azure deployment and improve logger i…
yehiarasheed Dec 19, 2025
18ae500
fix: update logger import to use default export from consola
yehiarasheed Dec 19, 2025
7dbe7ea
fix: update Azure deployment workflow and improve CORS configuration …
yehiarasheed Dec 19, 2025
6116559
fix(logger): types + global logger declaration and safer overrides
yehiarasheed Dec 19, 2025
91001d0
feat: add Vercel deployment workflow and update .gitignore for Vercel
yehiarasheed Dec 19, 2025
0299cd5
feat: update Vercel deployment workflow to include feat/azure-deploy …
yehiarasheed Dec 19, 2025
5a040b2
ci(workflows): allow manual workflow_dispatch for Vercel and Azure
yehiarasheed Dec 19, 2025
30967e2
Create vercel.json
yehiarasheed Dec 19, 2025
ae81814
Update vercel.json
yehiarasheed Dec 19, 2025
a102e7c
Update vercel-deploy.yml
yehiarasheed Dec 19, 2025
5b676b5
Update vercel.json
yehiarasheed Dec 19, 2025
38f9096
Update vercel-deploy.yml
yehiarasheed Dec 19, 2025
cb144fd
Update vercel-deploy.yml
yehiarasheed Dec 19, 2025
e5e350d
Update vercel.json
yehiarasheed Dec 19, 2025
5ca23bd
Update Vercel configuration for output directory and rewrites
yehiarasheed Dec 19, 2025
8e512e7
Add initial package.json with dependencies and scripts
yehiarasheed Dec 19, 2025
da098f5
Update Vercel deployment configuration and add missing vercel.json
yehiarasheed Jan 1, 2026
34aaf0b
Refactor API base URL handling across client components
yehiarasheed Jan 1, 2026
f3afb82
Enhance Azure deployment workflow and update server configurations
yehiarasheed Jan 1, 2026
b0af15f
Refactor logger initialization to use consola module and add error ha…
yehiarasheed Jan 1, 2026
b48e253
Refactor logger initialization to enhance compatibility with CommonJS…
yehiarasheed Jan 1, 2026
0d7d300
Update branch references in Azure and Vercel deployment workflows to …
yehiarasheed Jan 1, 2026
3dc6373
Merge branch 'main' into feat/azure-vercel-deployment
yehiarasheed Jan 1, 2026
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
10 changes: 5 additions & 5 deletions .github/workflows/azure-deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ on:
push:
branches:
- main
- feat/azure-deploy
- feat/azure-vercel-deployment
paths:
- "server/**"
- ".github/workflows/azure-deploy.yml"
Expand All @@ -26,18 +26,18 @@ jobs:
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: "22.x"
node-version: ${{ env.NODE_VERSION }}
cache: "npm"
cache-dependency-path: server/package-lock.json

- name: Install dependencies
- name: Create deployment package
run: |
cd server
npm ci --production
zip -r ../server-deploy.zip . -x "node_modules/*" ".env" ".env.*" "**/*.log"

- name: Deploy to Azure Web App
uses: azure/webapps-deploy@v3
with:
app-name: ${{ secrets.AZURE_WEBAPP_NAME }}
publish-profile: ${{ secrets.AZURE_WEBAPP_PUBLISH_PROFILE }}
package: ${{ env.AZURE_WEBAPP_PACKAGE_PATH }}
package: ./server-deploy.zip
57 changes: 53 additions & 4 deletions .github/workflows/vercel-deploy.yml
Original file line number Diff line number Diff line change
@@ -1,22 +1,71 @@
name: Deploy Frontend to Vercel

on:
push:
branches:
- main
- feat/azure-deploy
paths: ["client/**"]
- feat/azure-vercel-deployment
paths: [
"client/**",
"package.json",
"package-lock.json",
"vercel.json",
"client/vercel.json",
] # Added Vercel configs to trigger
pull_request:
branches:
- main
- feat/azure-vercel-deployment
paths:
[
"client/**",
"package.json",
"package-lock.json",
"vercel.json",
"client/vercel.json",
]
workflow_dispatch:

jobs:
deploy:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4

- name: Use Node.js 18
uses: actions/setup-node@v4
with:
node-version: 18
cache: "npm"
# FIX: Point to the actual location of your lock file
cache-dependency-path: "package-lock.json"

- name: Install dependencies
# FIX: Run in root because that's where package.json is
run: npm install

- name: Build frontend
# If your build script is in the root package.json:
run: npm run build
# OR if you must run the build inside the client folder:
# working-directory: ./client
# run: npm run build

- name: Choose Vercel deploy type
id: vercel
run: |
if [ "${{ github.event_name }}" = "push" ]; then
echo "args=--prod" >> $GITHUB_OUTPUT
else
echo "args=" >> $GITHUB_OUTPUT
fi

- name: Deploy to Vercel
uses: amondnet/vercel-action@v20
with:
vercel-token: ${{ secrets.VERCEL_TOKEN }}
vercel-org-id: ${{ secrets.VERCEL_ORG_ID }}
vercel-project-id: ${{ secrets.VERCEL_PROJECT_ID }}
working-directory: ./client
vercel-args: "--prod"
working-directory: ./ # Usually root if package.json is there
vercel-args: ${{ steps.vercel.outputs.args }}
152 changes: 152 additions & 0 deletions client/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
{
"name": "rest-express",
"version": "1.0.0",
"type": "module",
"license": "MIT",
"scripts": {
"dev": "cross-env NODE_ENV=development tsx server/index.ts",
"build": "vite build && esbuild server/index.ts --platform=node --packages=external --bundle --format=esm --outdir=dist",
"start": "NODE_ENV=production node dist/index.js",
"check": "tsc",
"db:push": "drizzle-kit push",
"lint": "eslint . --ext .js,.jsx,.ts,.tsx",
"lint:fix": "eslint . --ext .js,.jsx,.ts,.tsx --fix",
"format": "prettier --write \"**/*.{js,jsx,ts,tsx,json,css,scss,md}\"",
"format:check": "prettier --check \"**/*.{js,jsx,ts,tsx,json,css,scss,md}\"",
"prepare": "husky"
},
"dependencies": {
"@emailjs/browser": "^4.4.1",
"@emailjs/nodejs": "^5.0.2",
"@hookform/resolvers": "^3.10.0",
"@jridgewell/trace-mapping": "^0.3.25",
"@neondatabase/serverless": "^0.10.4",
"@radix-ui/react-accordion": "^1.2.4",
"@radix-ui/react-alert-dialog": "^1.1.7",
"@radix-ui/react-aspect-ratio": "^1.1.3",
"@radix-ui/react-avatar": "^1.1.4",
"@radix-ui/react-checkbox": "^1.1.5",
"@radix-ui/react-collapsible": "^1.1.4",
"@radix-ui/react-context-menu": "^2.2.7",
"@radix-ui/react-dialog": "^1.1.7",
"@radix-ui/react-dropdown-menu": "^2.1.7",
"@radix-ui/react-hover-card": "^1.1.7",
"@radix-ui/react-label": "^2.1.3",
"@radix-ui/react-menubar": "^1.1.7",
"@radix-ui/react-navigation-menu": "^1.2.6",
"@radix-ui/react-popover": "^1.1.7",
"@radix-ui/react-progress": "^1.1.3",
"@radix-ui/react-radio-group": "^1.2.4",
"@radix-ui/react-scroll-area": "^1.2.4",
"@radix-ui/react-select": "^2.1.7",
"@radix-ui/react-separator": "^1.1.3",
"@radix-ui/react-slider": "^1.2.4",
"@radix-ui/react-slot": "^1.2.0",
"@radix-ui/react-switch": "^1.1.4",
"@radix-ui/react-tabs": "^1.1.4",
"@radix-ui/react-toast": "^1.2.7",
"@radix-ui/react-toggle": "^1.1.3",
"@radix-ui/react-toggle-group": "^1.1.3",
"@radix-ui/react-tooltip": "^1.2.0",
"@react-oauth/google": "^0.12.2",
"@stripe/react-stripe-js": "^5.4.0",
"@stripe/stripe-js": "^8.5.2",
"@tanstack/react-query": "^5.60.5",
"@vercel/blob": "^2.0.0",
"axios": "^1.12.2",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"cmdk": "^1.1.1",
"connect-pg-simple": "^10.0.0",
"consola": "^3.4.2",
"date-fns": "^3.6.0",
"drizzle-orm": "^0.39.1",
"drizzle-zod": "^0.7.0",
"embla-carousel-react": "^8.6.0",
"express": "^4.21.2",
"express-session": "^1.18.1",
"framer-motion": "^11.18.2",
"googleapis": "^168.0.0",
"ical-generator": "^10.0.0",
"input-otp": "^1.4.2",
"lucide-react": "^0.554.0",
"memorystore": "^1.6.7",
"moment": "^2.30.1",
"next-themes": "^0.4.6",
"nodemailer": "^7.0.9",
"passport": "^0.7.0",
"passport-local": "^1.0.0",
"postcss-import": "^16.1.1",
"postcss-loader": "^8.2.0",
"react": "^18.3.1",
"react-big-calendar": "^1.19.4",
"react-day-picker": "^8.10.1",
"react-dom": "^18.3.1",
"react-hook-form": "^7.55.0",
"react-icons": "^5.4.0",
"react-image-crop": "^11.0.10",
"react-resizable-panels": "^2.1.7",
"react-router-dom": "^6.30.1",
"recharts": "^2.15.2",
"stripe": "^19.3.0",
"tailwind-merge": "^2.6.0",
"tailwindcss-animate": "^1.0.7",
"three": "^0.180.0",
"tw-animate-css": "^1.2.5",
"vaul": "^1.1.2",
"wouter": "^3.3.5",
"ws": "^8.18.0",
"xlsx": "^0.18.5",
"zod": "^3.24.2",
"zod-validation-error": "^3.4.0"
},
"devDependencies": {
"@eslint/js": "^9.39.1",
"@replit/vite-plugin-cartographer": "^0.3.1",
"@replit/vite-plugin-dev-banner": "^0.1.1",
"@replit/vite-plugin-runtime-error-modal": "^0.0.3",
"@tailwindcss/typography": "^0.5.15",
"@tailwindcss/vite": "^4.1.3",
"@types/axios": "^0.9.36",
"@types/connect-pg-simple": "^7.0.3",
"@types/express": "4.17.21",
"@types/express-session": "^1.18.0",
"@types/node": "20.16.11",
"@types/passport": "^1.0.16",
"@types/passport-local": "^1.0.38",
"@types/react": "^18.3.11",
"@types/react-big-calendar": "^1.16.3",
"@types/react-dom": "^18.3.1",
"@types/three": "^0.180.0",
"@types/ws": "^8.5.13",
"@typescript-eslint/eslint-plugin": "^8.46.3",
"@typescript-eslint/parser": "^8.46.3",
"autoprefixer": "^10.4.21",
"baseline-browser-mapping": "^2.9.9",
"cross-env": "^10.1.0",
"drizzle-kit": "^0.31.4",
"esbuild": "^0.25.0",
"eslint": "^9.39.1",
"eslint-config-prettier": "^10.1.8",
"eslint-plugin-prettier": "^5.5.4",
"eslint-plugin-react": "^7.37.5",
"eslint-plugin-react-hooks": "^7.0.1",
"eslint-plugin-unused-imports": "^4.3.0",
"husky": "^9.1.7",
"lint-staged": "^16.2.6",
"postcss": "^8.5.6",
"prettier": "^3.6.2",
"tailwindcss": "^3.4.17",
"tsx": "^4.20.5",
"typescript": "^5.9.3",
"vite": "^5.4.20"
},
"optionalDependencies": {
"bufferutil": "^4.0.8"
},
"lint-staged": {
"**/*.{js,jsx,ts,tsx,json,css,scss,md}": [
"prettier --write"
]
}
}
4 changes: 3 additions & 1 deletion client/src/components/BazaarList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Search, Store } from "lucide-react";
import { useToast } from "@/hooks/use-toast";
import { getApiBaseUrl } from "@/lib/apiBase";

export interface Bazaar {
_id: string;
Expand Down Expand Up @@ -44,6 +45,7 @@ export default function BazaarList({
}: BazaarListProps) {
const [searchTerm, setSearchTerm] = useState("");
const { toast } = useToast();
const API_BASE_URL = getApiBaseUrl();

const handleRegisterEvent = async (eventId: string) => {
try {
Expand All @@ -58,7 +60,7 @@ export default function BazaarList({
}

const response = await fetch(
`http://localhost:4000/api/events/${eventId}/register`,
`${API_BASE_URL}/api/events/${eventId}/register`,
{
method: "POST",
headers: {
Expand Down
4 changes: 2 additions & 2 deletions client/src/components/BigCalendarView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@
import { Card } from "@/components/ui/card";
import EventDetailsDialog from "@/components/EventsDetailsDialog";
import { Button } from "@/components/ui/button";
import { getApiBaseUrl } from "@/lib/apiBase";

const localizer = momentLocalizer(moment);
const API_BASE_URL =
import.meta.env.VITE_API_BASE_URL || "http://localhost:4000";
const API_BASE_URL = getApiBaseUrl();

interface Event {
_id: string;
Expand Down Expand Up @@ -40,7 +40,7 @@
export default function BigCalendarView({
events,
onEventClick,
onUnregister,

Check warning on line 43 in client/src/components/BigCalendarView.tsx

View workflow job for this annotation

GitHub Actions / ESLint & Prettier Check

'onUnregister' is defined but never used. Allowed unused args must match /^_/u
defaultDate,
defaultView = "month",
className = "",
Expand All @@ -65,13 +65,13 @@
}, [events]);

const handleSelectEvent = useCallback(
async (calendarEvent: any) => {

Check warning on line 68 in client/src/components/BigCalendarView.tsx

View workflow job for this annotation

GitHub Actions / ESLint & Prettier Check

Unexpected any. Specify a different type
const eventId = calendarEvent.id;
setIsLoadingDetails(true);
try {
// Fetch complete event details from the database
const token = localStorage.getItem("token");
logger.info(

Check warning on line 74 in client/src/components/BigCalendarView.tsx

View workflow job for this annotation

GitHub Actions / ESLint & Prettier Check

'logger' is not defined
"Fetching event:",
eventId,
"API URL:",
Expand All @@ -85,24 +85,24 @@
},
});

logger.info("API Response status:", response.status);

Check warning on line 88 in client/src/components/BigCalendarView.tsx

View workflow job for this annotation

GitHub Actions / ESLint & Prettier Check

'logger' is not defined

if (response.ok) {
const data = await response.json();
logger.info("API Response data:", data);

Check warning on line 92 in client/src/components/BigCalendarView.tsx

View workflow job for this annotation

GitHub Actions / ESLint & Prettier Check

'logger' is not defined
const eventData = data.data || data;
logger.info("Setting selected event:", eventData);

Check warning on line 94 in client/src/components/BigCalendarView.tsx

View workflow job for this annotation

GitHub Actions / ESLint & Prettier Check

'logger' is not defined
setSelectedEvent(eventData);
onEventClick?.(eventData);
} else {
// Fallback to the resource data if API call fails
logger.warn("API call failed, using fallback data");

Check warning on line 99 in client/src/components/BigCalendarView.tsx

View workflow job for this annotation

GitHub Actions / ESLint & Prettier Check

'logger' is not defined
const event = calendarEvent.resource as Event;
setSelectedEvent(event);
onEventClick?.(event);
}
} catch (error) {
logger.error("Error fetching event details:", error);

Check warning on line 105 in client/src/components/BigCalendarView.tsx

View workflow job for this annotation

GitHub Actions / ESLint & Prettier Check

'logger' is not defined
// Fallback to the resource data if fetch fails
const event = calendarEvent.resource as Event;
setSelectedEvent(event);
Expand Down
3 changes: 2 additions & 1 deletion client/src/components/CalendarPopover.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@ import {
} from "@/components/ui/popover";
import MiniCalendar from "./MiniCalendar";
import { useLocation } from "wouter";
import { getApiBaseUrl } from "@/lib/apiBase";

const API_BASE_URL = "http://localhost:4000";
const API_BASE_URL = getApiBaseUrl();

interface Event {
_id: string;
Expand Down
5 changes: 3 additions & 2 deletions client/src/components/CreateEventForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ import { Checkbox } from "@/components/ui/checkbox";
import { Info, Clock, CalendarIcon } from "lucide-react";
import { useToast } from "@/hooks/use-toast";
import { cn } from "@/lib/utils";
import { logger } from "@/lib/logger";
import { getApiBaseUrl } from "@/lib/apiBase";

export interface CreateEventFormValues {
name: string;
Expand Down Expand Up @@ -104,8 +106,7 @@ export default function CreateEventForm({

(async () => {
try {
const baseUrl =
(import.meta as any).env.VITE_API_URL || "http://localhost:4000";
const baseUrl = getApiBaseUrl();
const res = await fetch(`${baseUrl}/api/users/professors`, {
headers: { Authorization: `Bearer ${token}` },
});
Expand Down
5 changes: 4 additions & 1 deletion client/src/components/CreateGymSessionDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ import {
} from "@/components/ui/popover";
import { Calendar } from "@/components/ui/calendar";
import { cn } from "@/lib/utils";
import { logger } from "@/lib/logger";
import { getApiBaseUrl } from "@/lib/apiBase";

type CreateGymSessionDialogProps = {
open: boolean;
Expand All @@ -48,6 +50,7 @@ export default function CreateGymSessionDialog({
onOpenChange,
onSuccess,
}: CreateGymSessionDialogProps) {
const API_BASE_URL = getApiBaseUrl();
const [loading, setLoading] = useState(false);
const [formData, setFormData] = useState<{
date: Date | undefined;
Expand Down Expand Up @@ -96,7 +99,7 @@ export default function CreateGymSessionDialog({
};

const response = await fetch(
"http://localhost:4000/api/facilities/admin/gym/sessions",
`${API_BASE_URL}/api/facilities/admin/gym/sessions`,
{
method: "POST",
headers: {
Expand Down
4 changes: 3 additions & 1 deletion client/src/components/CreatePrivilegedUserForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
import { getApiBaseUrl } from "@/lib/apiBase";

interface Props {
onSuccess?: () => void;
Expand All @@ -20,6 +21,7 @@ export default function CreatePrivilegedUserForm({
onSuccess,
onCancel,
}: Props) {
const API_BASE_URL = getApiBaseUrl();
const [form, setForm] = useState({
firstName: "",
lastName: "",
Expand All @@ -37,7 +39,7 @@ export default function CreatePrivilegedUserForm({
setError(null);
try {
await axios.post(
"http://localhost:4000/api/users/create-management-account",
`${API_BASE_URL}/api/users/create-management-account`,
form,
{
headers: {
Expand Down
Loading
Loading