Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
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
38 changes: 36 additions & 2 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,50 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v3
uses: actions/checkout@v4

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20
cache: npm

- name: Create CI environment file
run: |
cat <<'EOF' > .env
# Frontend (Vite) - Using placeholder values for CI build
VITE_FIREBASE_API_KEY=
VITE_FIREBASE_AUTH_DOMAIN=
VITE_FIREBASE_PROJECT_ID=
VITE_FIREBASE_STORAGE_BUCKET=
VITE_FIREBASE_MESSAGING_SENDER_ID=
VITE_FIREBASE_APP_ID=
VITE_FIREBASE_MEASUREMENT_ID=
VITE_FIREBASE_RECAPTCHA_SITE_KEY=
VITE_GOOGLE_OAUTH_CLIENT_ID=
VITE_GEMINI_API_KEY=
VITE_PUBLIC_ONCHAINKIT_API_KEY=
VITE_BASE_RPC_URL=https://sepolia.base.org
VITE_FRACTAL_RECIPE_CONTRACT_ADDRESS=
VITE_FRACTAL_RECIPE_DEPLOY_BLOCK=0

# Backend (server) - Using minimal values for build
PORT=4000
JWT_SECRET=ci-secret
JWT_TTL_SECONDS=3600
CORS_ORIGIN=http://localhost:5173
FIREBASE_PROJECT_ID=ci
FIREBASE_CLIENT_EMAIL=
FIREBASE_PRIVATE_KEY="-----BEGIN PRIVATE KEY-----\n\n-----END PRIVATE KEY-----\n"
GOOGLE_OAUTH_CLIENT_ID=
PASSWORD_MIN_LENGTH=10
PWD_RESET_OTP_TTL_MS=600000
PWD_RESET_MAX_ATTEMPTS=5
WEBHOOK_SECRET=ci-webhook-secret
EOF

- name: Install dependencies
run: npm install
run: npm ci

- name: Build project
run: npm run build
Expand Down
58 changes: 29 additions & 29 deletions components/auth/EmailLinkAuthExample.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useState, useEffect } from 'react';
import { useState, useEffect, useCallback } from 'react';
import type { ActionCodeSettings } from 'firebase/auth';
import {
sendEmailSignInLink,
Expand All @@ -19,13 +19,37 @@ export function EmailLinkAuthExample() {
const [error, setError] = useState('');
const [isCompletingSignIn, setIsCompletingSignIn] = useState(false);

const handleCompleteSignIn = useCallback(async (providedEmail?: string) => {
setError('');
setStatus('Completing sign-in...');

try {
const result = await completeEmailSignIn(providedEmail || email);

setStatus(`Successfully signed in as ${result.user.email}`);
// Handle successful sign-in (e.g., redirect to dashboard)

} catch (err) {
const errorMessage = err instanceof Error ? err.message : 'Failed to complete sign-in';

// If email is missing, prompt user to enter it
if (errorMessage.includes('Email address is required')) {
setError('Please enter your email to complete sign-in');
setIsCompletingSignIn(true);
} else {
setError(errorMessage);
}
setStatus('');
}
}, [email]);

useEffect(() => {
// Check if current URL is a sign-in link
if (isEmailSignInLink()) {
setIsCompletingSignIn(true);
handleCompleteSignIn();
void handleCompleteSignIn();
}
}, []);
}, [handleCompleteSignIn]);

const handleSendLink = async () => {
setError('');
Expand Down Expand Up @@ -54,30 +78,6 @@ export function EmailLinkAuthExample() {
}
};

const handleCompleteSignIn = async (providedEmail?: string) => {
setError('');
setStatus('Completing sign-in...');

try {
const result = await completeEmailSignIn(providedEmail || email);

setStatus(`Successfully signed in as ${result.user.email}`);
// Handle successful sign-in (e.g., redirect to dashboard)

} catch (err) {
const errorMessage = err instanceof Error ? err.message : 'Failed to complete sign-in';

// If email is missing, prompt user to enter it
if (errorMessage.includes('Email address is required')) {
setError('Please enter your email to complete sign-in');
setIsCompletingSignIn(true);
} else {
setError(errorMessage);
}
setStatus('');
}
};

if (isCompletingSignIn) {
return (
<div className="max-w-md mx-auto p-6 bg-white rounded-lg shadow">
Expand All @@ -95,7 +95,7 @@ export function EmailLinkAuthExample() {
<input
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => setEmail(e.target.value)}
placeholder="you@example.com"
className="w-full px-3 py-2 border rounded focus:ring-2 focus:ring-blue-500"
/>
Expand Down Expand Up @@ -137,7 +137,7 @@ export function EmailLinkAuthExample() {
<input
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => setEmail(e.target.value)}
placeholder="you@example.com"
className="w-full px-3 py-2 border rounded focus:ring-2 focus:ring-blue-500"
/>
Expand Down
4 changes: 2 additions & 2 deletions components/auth/PhoneAuthExample.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ export function PhoneAuthExample() {
<input
type="tel"
value={phoneNumber}
onChange={(e) => setPhoneNumber(e.target.value)}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => setPhoneNumber(e.target.value)}
placeholder="+1 234 567 8900"
className="w-full px-3 py-2 border rounded focus:ring-2 focus:ring-blue-500"
/>
Expand Down Expand Up @@ -101,7 +101,7 @@ export function PhoneAuthExample() {
<input
type="text"
value={verificationCode}
onChange={(e) => setVerificationCode(e.target.value)}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => setVerificationCode(e.target.value)}
placeholder="123456"
maxLength={6}
className="w-full px-3 py-2 border rounded focus:ring-2 focus:ring-blue-500"
Expand Down