Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
7eee97b
feat: Implement user profile and workout history
JoaoVijales Nov 17, 2025
be1a4bf
feat: Refactor workout session and history tracking
JoaoVijales Nov 19, 2025
3f0e54e
feat: Integrate Supabase authentication and user data management
JoaoVijales Nov 21, 2025
1f848a6
feat: Create initial menstrual cycle if none exists
JoaoVijales Nov 21, 2025
31bee1e
fix: Resolve workout screen and cycle logic bugs
JoaoVijales Nov 21, 2025
1f018bb
feat: Refactor workout session management and database schema
JoaoVijales Nov 21, 2025
14d13d3
feat: Display workout statistics on home screen
JoaoVijales Nov 21, 2025
454bc43
feat: Implement user plan table and policies
JoaoVijales Nov 21, 2025
314a3f3
feat: Migrate project to Next.js App Router
JoaoVijales Nov 22, 2025
3af989b
feat: Implement Stripe access control and payment redirect pages
JoaoVijales Nov 22, 2025
fac54bc
feat: Implement global brand identity styles and refactor success pag…
JoaoVijales Nov 23, 2025
9f5fd13
feat: Refactor Stripe webhook and improve auth UI
JoaoVijales Nov 24, 2025
8fe63c3
feat: Implement unit tests for useFlowFitData and useWorkoutSession h…
JoaoVijales Nov 25, 2025
3acb4e6
feat: Add Stripe webhook handling tables and policies
JoaoVijales Nov 25, 2025
75f8e6d
feat: Add professional README and comprehensive documentation
JoaoVijales Nov 25, 2025
4c8af07
feat: Add RLS policies for stripe_unmatched_sessions
JoaoVijales Nov 25, 2025
cc032b0
fix: Update emoji for 'Elásticos de Resistência' in onboarding
JoaoVijales Nov 25, 2025
9b4bbab
feat: Enable Supabase data persistence for onboarding
JoaoVijales Nov 25, 2025
ffd5afc
fix: Resolve TypeScript errors in FlowFitContext.tsx after refactoring
JoaoVijales Nov 25, 2025
040b09f
fix: Align onboarding field names with Supabase schema (snake_case)
JoaoVijales Nov 25, 2025
af56653
refactor: Use Supabase upsert for updateUserProfile function
JoaoVijales Nov 25, 2025
3f5fdad
docs: Update bd_base.sql with UNIQUE constraint for user_profiles.use…
JoaoVijales Nov 25, 2025
5737bfc
refactor: Update updateUserProfile to use UPDATE-then-INSERT logic fo…
JoaoVijales Nov 25, 2025
c09417e
fix: Corrected user ID for updateUserProfile and retained debug log
JoaoVijales Nov 25, 2025
bbe6bf4
Fix: Correct userId field in SubscriptionRequiredScreen.tsx
JoaoVijales Nov 25, 2025
c5aa133
Refactor: Adjust user flow after onboarding and for subscription checks
JoaoVijales Nov 25, 2025
a2ba3aa
Fix: Resolve endless loading issue on session loss
JoaoVijales Nov 25, 2025
6d33e5d
Fix: Robust screen determination in FlowFitApp to prevent stuck loading
JoaoVijales Nov 25, 2025
d8acea4
Fix: Handle pre-update onboarded users for subscription flow
JoaoVijales Nov 25, 2025
92b1a72
Refactor: Implement 'Subscription Notice Page' user flow
JoaoVijales Nov 25, 2025
55141fb
Feat: Apply application styling to SubscriptionRequiredScreen
JoaoVijales Nov 25, 2025
e0de531
Fix: Resolve compilation error by returning initiateCheckoutSession f…
JoaoVijales Nov 25, 2025
cf9be19
Feat: Redesign app menu based on MVP frontend reference
JoaoVijales Nov 25, 2025
dd0b16a
feat: Integrate Stripe checkout session creation after onboarding
JoaoVijales Nov 25, 2025
73b9a4c
feat: Implement global authentication redirect middleware and update …
JoaoVijales Nov 26, 2025
d4f6e03
Fix: Resolve 404 error by adjusting middleware authentication logic
JoaoVijales Nov 26, 2025
5d27f71
Refactor: Migrate Next.js middleware to proxy convention
JoaoVijales Nov 26, 2025
6522d46
Fix: Resolve Supabase 403 Forbidden error
JoaoVijales Nov 26, 2025
4d5e3a3
Fix: Align equipment values with database schema
JoaoVijales Nov 27, 2025
8ff62ae
Fix: Resolve loading state bug in FlowFitApp
JoaoVijales Nov 27, 2025
62d4ce5
Refactor: Revamp SettingsScreen styles to match reference design
JoaoVijales Nov 27, 2025
f109542
Fix: Resolve multiple bugs across app screens
JoaoVijales Nov 27, 2025
5b364b4
Fix: Resolve infinite loading on HomeScreen
JoaoVijales Nov 27, 2025
d18225b
refactor: Improves calendar phase visualization and home screen loading
JoaoVijales Nov 27, 2025
84ad263
feat: Implement robust loading for HomeScreen and add debug logs
JoaoVijales Nov 27, 2025
7ffb813
fix: Resolve HomeScreen infinite loading and data population
JoaoVijales Nov 27, 2025
7c9bdeb
feat: Enhance FeedbackScreen with styled UI and adapted logic
JoaoVijales Nov 27, 2025
014d73b
feat: Enhance HistoryScreen with styled UI and adapted logic
JoaoVijales Nov 27, 2025
f8e40fa
refactor: Decouple bottom navigation from FlowFitApp
JoaoVijales Nov 27, 2025
52cb705
fix: Initialize workout session on Home Screen
JoaoVijales Nov 27, 2025
beca1cb
feat: Add debug logs to useWorkoutSession for feedback bug
JoaoVijales Nov 27, 2025
f0f9857
fix: Resolve useMemo import error in HomeScreen
JoaoVijales Nov 27, 2025
b4df021
feat: Add debug logs to startWorkoutSession for RLS policy investigation
JoaoVijales Nov 27, 2025
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
30 changes: 27 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,44 @@
/node_modules
/.pnp
.pnp.js
.pnp.*
.yarn/*
!.yarn/patches
!.yarn/plugins
!.yarn/releases
!.yarn/versions

# testing
/coverage

# next.js
/.next/
/out/

# production
/build

# misc
.DS_Store
*.pem

# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.pnpm-debug.log*

# env files (can opt-in for committing if needed)
.env.local
.env.development.local
.env.test.local
.env.production.local
.env
.env*

npm-debug.log*
yarn-debug.log*
yarn-error.log*
# vercel
.vercel

# typescript
*.tsbuildinfo
next-env.d.ts
129 changes: 129 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
# FlowFit Next.js Application

A modern fitness application built with Next.js, React, and TypeScript, leveraging Supabase for backend services (authentication, database) and Stripe for subscription management. It features user authentication, personalized workout tracking, a calendar to manage fitness schedules, and tailored content, primarily focusing on women's fitness.

## Features

* **User Authentication:** Secure sign-up, login, and password recovery powered by Supabase Auth.
* **Personalized Workout Tracking:** Track and manage custom workout routines and progress.
* **Subscription Management:** Handle premium content and features through Stripe-powered subscriptions.
* **Fitness Calendar:** Schedule and visualize your workout plans.
* **User Profiles & Settings:** Manage personal information and application preferences.
* **Responsive Design:** Optimized for various devices, from mobile to desktop.

## Technologies Used

* **Framework:** Next.js 16.0.3 (React 19.2.0)
* **Language:** TypeScript 5
* **Styling:** Tailwind CSS, PostCSS, Autoprefixer
* **Backend Services:** Supabase (Auth, Database)
* **Payment Processing:** Stripe
* **Icons:** Lucide React
* **Date Management:** React Calendar
* **Testing:** Jest, React Testing Library
* **Environment Variables:** Dotenv
* **Linting:** ESLint
* **Build Tool:** Web-vitals

## Getting Started

Follow these instructions to get a copy of the project up and running on your local machine for development and testing purposes.

### Prerequisites

Make sure you have the following installed:

* Node.js (LTS version recommended)
* npm or Yarn

### Installation

1. **Clone the repository:**
```bash
git clone https://github.com/your-username/flowfit-next.git
cd flowfit-next
```
2. **Install dependencies:**
```bash
npm install
# or
yarn install
```

### Environment Variables

Create a `.env.local` file in the root of your project and add the following environment variables. Obtain these from your Supabase and Stripe dashboards.

```
NEXT_PUBLIC_SUPABASE_URL=your_supabase_url
NEXT_PUBLIC_SUPABASE_ANON_KEY=your_supabase_anon_key
STRIPE_SECRET_KEY=your_stripe_secret_key
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=your_stripe_publishable_key
STRIPE_WEBHOOK_SECRET=your_stripe_webhook_secret
# Optionally, if Firebase is used:
NEXT_PUBLIC_FIREBASE_API_KEY=your_firebase_api_key
NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN=your_firebase_auth_domain
NEXT_PUBLIC_FIREBASE_PROJECT_ID=your_firebase_project_id
NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET=your_firebase_storage_bucket
NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID=your_firebase_messaging_sender_id
NEXT_PUBLIC_FIREBASE_APP_ID=your_firebase_app_id
```

### Running the Application

To run the application in development mode:

```bash
npm run dev
# or
yarn dev
```

Open [http://localhost:3000](http://localhost:3000) in your browser to see the result.

## Project Structure

```
.
├── app/ # Next.js App Router root
│ ├── api/ # API routes (e.g., Stripe webhooks, checkout sessions)
│ ├── cancel/ # Page for cancelled payments
│ ├── success/ # Page for successful payments
│ ├── favicon.ico
│ ├── globals.css
│ ├── layout.tsx # Root layout for the application
│ └── page.tsx # Main entry page
├── public/ # Static assets
├── src/
│ ├── components/ # Reusable React components (Auth, Home, Workout, etc.)
│ ├── context/ # React Context providers
│ ├── hooks/ # Custom React hooks
│ ├── types/ # TypeScript type definitions
│ └── utils/ # Utility functions (API calls, Supabase client, etc.)
├── reference_files/ # Contains SQL schema, design documents, and examples
├── jest.config.js # Jest test configuration
├── next.config.ts # Next.js configuration
├── package.json # Project dependencies and scripts
├── postcss.config.js # PostCSS configuration
├── tailwind.config.ts # Tailwind CSS configuration
├── tsconfig.json # TypeScript configuration
└── ... # Other configuration files
```

## API Endpoints

The application exposes several API endpoints under `app/api` for server-side operations:

* `/api/create-checkout-session`: Handles the creation of new Stripe checkout sessions for subscriptions.
* `/api/create-customer-portal-session`: Manages redirecting users to the Stripe customer portal for subscription management.
* `/api/stripe-webhook`: Endpoint for Stripe webhooks to handle asynchronous events (e.g., successful payments, subscription changes).

## Testing

To run the unit and integration tests:

```bash
npm test
# or
yarn test
```
78 changes: 78 additions & 0 deletions __mocks__/@supabase/supabase-js.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
// __mocks__/@supabase/supabase-js.ts
import { jest } from '@jest/globals';

const mockSelect = jest.fn(() => ({
eq: jest.fn(() => ({
single: jest.fn(() => ({ data: {}, error: null })),
maybeSingle: jest.fn(() => ({ data: {}, error: null })),
data: [], // Default empty data
error: null,
})),
returns: jest.fn(() => ({ data: [], error: null })),
order: jest.fn(() => ({ data: [], error: null })),
limit: jest.fn(() => ({ data: [], error: null })),
// Add other methods as needed, e.g., gt, lt, in, etc.
}));

const mockFrom = jest.fn(() => ({
select: mockSelect,
insert: jest.fn(() => ({ data: {}, error: null })),
update: jest.fn(() => ({ data: {}, error: null })),
delete: jest.fn(() => ({ data: {}, error: null })),
// Add other table operations as needed
}));

const mockSignInWithPassword = jest.fn(() => ({ data: { user: { id: 'mock-user-id', email: 'test@example.com' }, session: { access_token: 'mock-token' } }, error: null }));
const mockSignUp = jest.fn(() => ({ data: { user: null, session: null }, error: null }));
const mockSignOut = jest.fn(() => ({ error: null }));
const mockGetUser = jest.fn(() => ({ data: { user: { id: 'mock-user-id', email: 'test@example.com' } }, error: null }));
const mockOnAuthStateChange = jest.fn(() => {
const unsubscribe = jest.fn();
const data = { subscription: { unsubscribe } };
return { data, error: null };
});
const mockUpdateUser = jest.fn(() => ({ data: { user: { id: 'mock-user-id', email: 'test@example.com' } }, error: null }));
const mockResetPasswordForEmail = jest.fn(() => ({ error: null }));

const mockAuth = jest.fn(() => ({
signInWithPassword: mockSignInWithPassword,
signUp: mockSignUp,
signOut: mockSignOut,
getUser: mockGetUser,
onAuthStateChange: mockOnAuthStateChange,
updateUser: mockUpdateUser,
resetPasswordForEmail: mockResetPasswordForEmail,
getSession: jest.fn(() => ({ data: { session: { access_token: 'mock-token' } }, error: null })),
setSession: jest.fn(() => ({ data: { session: { access_token: 'mock-token' } }, error: null })),
// Add other auth methods as needed
}));

const mockStorage = jest.fn(() => ({
from: jest.fn(() => ({
upload: jest.fn(() => ({ data: { path: 'mock/path' }, error: null })),
download: jest.fn(() => ({ data: new Blob(), error: null })),
getPublicUrl: jest.fn(() => ({ data: { publicUrl: 'http://mock.url/path' }, error: null })),
})),
}));

export const createClient = jest.fn(() => ({
from: mockFrom,
auth: mockAuth(), // Call auth() to get the mock object
storage: mockStorage(), // Call storage() to get the mock object
// Add other top-level Supabase client methods as needed
}));

// Export specific mocks so tests can reset them or assert against them
export {
mockFrom,
mockSelect,
mockAuth,
mockSignInWithPassword,
mockSignUp,
mockSignOut,
mockGetUser,
mockOnAuthStateChange,
mockUpdateUser,
mockResetPasswordForEmail,
mockStorage,
};
75 changes: 75 additions & 0 deletions __mocks__/stripe.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
// __mocks__/stripe.ts
import { jest } from '@jest/globals';

const mockCheckoutSessionsCreate = jest.fn((params) =>
Promise.resolve({
id: 'mock_session_id',
url: 'https://mock-checkout-url.com',
...params,
})
);

const mockBillingPortalSessionsCreate = jest.fn((params) =>
Promise.resolve({
id: 'mock_portal_session_id',
url: 'https://mock-portal-url.com',
...params,
})
);

const mockWebhooksConstructEvent = jest.fn((payload, signature, secret) => {
// Simulate successful construction by returning a mock event object
return {
id: 'evt_mock',
object: 'event',
type: 'checkout.session.completed', // Default mock event type
data: {
object: {
id: 'cs_mock_checkout_session',
customer: 'cus_mock_customer',
subscription: 'sub_mock_subscription',
client_reference_id: 'mock-user-id',
metadata: {
userId: 'mock-user-id',
},
},
},
};
});

// Mock the Stripe object itself
const mockStripe = jest.fn((apiKey) => ({
checkout: {
sessions: {
create: mockCheckoutSessionsCreate,
retrieve: jest.fn((id) => Promise.resolve({ id, status: 'complete', customer: 'cus_mock_customer' })),
},
},
billingPortal: {
sessions: {
create: mockBillingPortalSessionsCreate,
},
},
webhooks: {
constructEvent: mockWebhooksConstructEvent,
},
customers: {
retrieve: jest.fn((id) => Promise.resolve({ id, email: 'mock_customer@example.com' })),
},
subscriptions: {
retrieve: jest.fn((id) => Promise.resolve({ id, status: 'active', customer: 'cus_mock_customer' })),
},
// Add other Stripe services and methods as needed
}));

// We need to export a default function because the stripe package is typically imported
// like `import Stripe from 'stripe';` and then initialized `new Stripe(apiKey)`.
// Our mock needs to replicate this behavior.
module.exports = mockStripe;

// Export specific mocks so tests can reset them or assert against them
export {
mockCheckoutSessionsCreate,
mockBillingPortalSessionsCreate,
mockWebhooksConstructEvent,
};
9 changes: 9 additions & 0 deletions __mocks__/uuid.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
'use strict';

// __mocks__/uuid.js
// This file is a manual mock for the 'uuid' package.
// Jest will automatically use this mock when 'uuid' is imported in tests.

module.exports = {
v4: jest.fn(() => 'mock-uuid-v4'),
};
Loading