Add Stripe embedded onboarding

- Update StripeConnectOnboarding component with embedded flow
- Add new Stripe routes and service methods for embedded onboarding
- Update EarningsStatus and EarningsDashboard to support new flow
- Add required frontend dependencies

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
jackiettran
2026-01-02 18:26:53 -05:00
parent e153614993
commit 6853ae264c
8 changed files with 243 additions and 39 deletions

View File

@@ -1,6 +1,6 @@
import React, { useState, useEffect } from "react";
import { Link } from "react-router-dom";
import { rentalAPI, userAPI } from "../services/api";
import { rentalAPI, userAPI, stripeAPI } from "../services/api";
import { Rental, User } from "../types";
import StripeConnectOnboarding from "../components/StripeConnectOnboarding";
import EarningsStatus from "../components/EarningsStatus";
@@ -12,11 +12,17 @@ interface EarningsData {
rentalsWithEarnings: Rental[];
}
interface AccountStatus {
detailsSubmitted: boolean;
payoutsEnabled: boolean;
}
const EarningsDashboard: React.FC = () => {
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
const [earningsData, setEarningsData] = useState<EarningsData | null>(null);
const [userProfile, setUserProfile] = useState<User | null>(null);
const [accountStatus, setAccountStatus] = useState<AccountStatus | null>(null);
const [showOnboarding, setShowOnboarding] = useState(false);
useEffect(() => {
@@ -28,11 +34,28 @@ const EarningsDashboard: React.FC = () => {
try {
const response = await userAPI.getProfile();
setUserProfile(response.data);
// If user has a Stripe account, fetch account status
if (response.data.stripeConnectedAccountId) {
await fetchAccountStatus();
}
} catch (err) {
console.error("Failed to fetch user profile:", err);
}
};
const fetchAccountStatus = async () => {
try {
const response = await stripeAPI.getAccountStatus();
setAccountStatus({
detailsSubmitted: response.data.detailsSubmitted,
payoutsEnabled: response.data.payoutsEnabled,
});
} catch (err) {
console.error("Failed to fetch account status:", err);
}
};
const fetchEarningsData = async () => {
try {
// Get completed rentals where user is the owner
@@ -99,6 +122,7 @@ const EarningsDashboard: React.FC = () => {
}
const hasStripeAccount = !!userProfile?.stripeConnectedAccountId;
const isOnboardingComplete = accountStatus?.detailsSubmitted ?? false;
return (
<div className="container mt-4">
@@ -243,6 +267,7 @@ const EarningsDashboard: React.FC = () => {
<div className="card-body">
<EarningsStatus
hasStripeAccount={hasStripeAccount}
isOnboardingComplete={isOnboardingComplete}
onSetupClick={() => setShowOnboarding(true)}
/>
</div>
@@ -284,6 +309,7 @@ const EarningsDashboard: React.FC = () => {
<StripeConnectOnboarding
onComplete={handleSetupComplete}
onCancel={() => setShowOnboarding(false)}
hasExistingAccount={hasStripeAccount}
/>
)}
</div>