feat: Add No Website button to onboarding Step 2 with business description form

This commit is contained in:
Om-Singh1808
2025-09-04 04:29:56 +05:30
committed by ي
parent 5dc756f062
commit 201960ce9d
10 changed files with 499 additions and 2 deletions

View File

@@ -0,0 +1,49 @@
import { apiClient } from './client';
console.log('🔄 Loading Business Info API client...');
export interface BusinessInfo {
user_id?: number;
business_description: string;
industry?: string;
target_audience?: string;
business_goals?: string;
}
export interface BusinessInfoResponse extends BusinessInfo {
id: number;
created_at: string;
updated_at: string;
}
export const businessInfoApi = {
saveBusinessInfo: async (data: BusinessInfo): Promise<BusinessInfoResponse> => {
console.log('API: Saving business info', data);
const response = await apiClient.post<BusinessInfoResponse>('/onboarding/business-info', data);
console.log('API: Business info saved successfully', response.data);
return response.data;
},
getBusinessInfo: async (id: number): Promise<BusinessInfoResponse> => {
console.log(`API: Getting business info for ID: ${id}`);
const response = await apiClient.get<BusinessInfoResponse>(`/onboarding/business-info/${id}`);
console.log('API: Business info retrieved successfully', response.data);
return response.data;
},
getBusinessInfoByUserId: async (userId: number): Promise<BusinessInfoResponse> => {
console.log(`API: Getting business info for user ID: ${userId}`);
const response = await apiClient.get<BusinessInfoResponse>(`/onboarding/business-info/user/${userId}`);
console.log('API: Business info retrieved successfully by user ID', response.data);
return response.data;
},
updateBusinessInfo: async (id: number, data: BusinessInfo): Promise<BusinessInfoResponse> => {
console.log(`API: Updating business info for ID: ${id}`, data);
const response = await apiClient.put<BusinessInfoResponse>(`/onboarding/business-info/${id}`, data);
console.log('API: Business info updated successfully', response.data);
return response.data;
},
};
console.log('✅ Business Info API client loaded successfully!');

View File

@@ -0,0 +1,145 @@
import React, { useState, useEffect } from 'react';
import { Box, Button, TextField, Typography, Card, CardContent, CircularProgress, Alert } from '@mui/material';
import { ArrowBack as ArrowBackIcon, Save as SaveIcon, CheckCircle as CheckCircleIcon } from '@mui/icons-material';
import { businessInfoApi, BusinessInfo } from '../../api/businessInfo';
interface BusinessDescriptionStepProps {
onBack: () => void;
onContinue: () => void;
}
const BusinessDescriptionStep: React.FC<BusinessDescriptionStepProps> = ({ onBack, onContinue }) => {
const [formData, setFormData] = useState<BusinessInfo>({
business_description: '',
industry: '',
target_audience: '',
business_goals: '',
});
const [loading, setLoading] = useState(false);
const [error, setError] = useState<string | null>(null);
const [success, setSuccess] = useState<string | null>(null);
const handleChange = (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {
const { name, value } = e.target;
setFormData(prev => ({ ...prev, [name]: value }));
};
const handleSaveAndContinue = async () => {
setError(null);
setSuccess(null);
setLoading(true);
console.log('🚀 Attempting to save business info:', formData);
try {
// Simulate user_id for now, replace with actual user_id from auth context later
const userId = 1;
const dataToSave = { ...formData, user_id: userId };
const response = await businessInfoApi.saveBusinessInfo(dataToSave);
console.log('✅ Business info saved to DB:', response);
setSuccess('Business information saved successfully!');
setTimeout(() => {
onContinue();
}, 1500); // Give user time to see success message
} catch (err) {
console.error('❌ Error saving business info:', err);
setError('Failed to save business information. Please try again.');
} finally {
setLoading(false);
}
};
return (
<Box sx={{ mt: 4 }}>
<Typography variant="h5" gutterBottom>
Tell us about your business
</Typography>
<Typography variant="body1" color="textSecondary" sx={{ mb: 3 }}>
Since you don't have a website, please provide a description of your business. This will help ALwrity understand your brand and tailor its services.
</Typography>
<Card sx={{ p: 3, mb: 3 }}>
<CardContent>
{error && <Alert severity="error" sx={{ mb: 2 }}>{error}</Alert>}
{success && <Alert severity="success" sx={{ mb: 2 }} icon={<CheckCircleIcon fontSize="inherit" />}>{success}</Alert>}
<TextField
label="Business Description"
name="business_description"
value={formData.business_description}
onChange={handleChange}
fullWidth
multiline
rows={4}
margin="normal"
required
helperText={`${formData.business_description.length}/1000 characters`}
inputProps={{ maxLength: 1000 }}
disabled={loading}
/>
<TextField
label="Industry"
name="industry"
value={formData.industry}
onChange={handleChange}
fullWidth
margin="normal"
helperText={`${formData.industry.length}/100 characters`}
inputProps={{ maxLength: 100 }}
disabled={loading}
/>
<TextField
label="Target Audience"
name="target_audience"
value={formData.target_audience}
onChange={handleChange}
fullWidth
multiline
rows={2}
margin="normal"
helperText={`${(formData.target_audience || '').length}/500 characters`}
inputProps={{ maxLength: 500 }}
disabled={loading}
/>
<TextField
label="Business Goals"
name="business_goals"
value={formData.business_goals}
onChange={handleChange}
fullWidth
multiline
rows={3}
margin="normal"
helperText={`${(formData.business_goals || '').length}/1000 characters`}
inputProps={{ maxLength: 1000 }}
disabled={loading}
/>
</CardContent>
</Card>
<Box sx={{ display: 'flex', justifyContent: 'space-between', mt: 3 }}>
<Button
variant="outlined"
color="secondary"
onClick={onBack}
startIcon={<ArrowBackIcon />}
disabled={loading}
>
Back
</Button>
<Button
variant="contained"
color="primary"
onClick={handleSaveAndContinue}
endIcon={loading ? <CircularProgress size={20} color="inherit" /> : <SaveIcon />}
disabled={loading || !formData.business_description}
>
{loading ? 'Saving...' : 'Save & Continue'}
</Button>
</Box>
</Box>
);
};
export default BusinessDescriptionStep;

View File

@@ -1,4 +1,5 @@
import React, { useState, useEffect } from 'react';
import BusinessDescriptionStep from './BusinessDescriptionStep';
import {
Box,
Button,
@@ -178,6 +179,7 @@ const WebsiteStep: React.FC<WebsiteStepProps> = ({ onContinue, updateHeaderConte
const [useAnalysisForGenAI, setUseAnalysisForGenAI] = useState(true);
const [domainName, setDomainName] = useState<string>('');
const [hasCheckedExisting, setHasCheckedExisting] = useState(false);
const [showBusinessForm, setShowBusinessForm] = useState(false);
const [progress, setProgress] = useState<AnalysisProgress[]>([
{ step: 1, message: 'Validating website URL', completed: false },
{ step: 2, message: 'Crawling website content', completed: false },
@@ -926,6 +928,22 @@ const WebsiteStep: React.FC<WebsiteStepProps> = ({ onContinue, updateHeaderConte
</Zoom>
);
// Conditional rendering for business description form
if (showBusinessForm) {
return (
<BusinessDescriptionStep
onBack={() => {
console.log(' Going back to website form...');
setShowBusinessForm(false);
}}
onContinue={() => {
console.log(' Business info completed, proceeding to next step...');
onContinue();
}}
/>
);
}
return (
<Box sx={{ maxWidth: 900, mx: 'auto', p: 3 }}>
{/* Enhanced Explanatory Text */}
@@ -978,6 +996,22 @@ const WebsiteStep: React.FC<WebsiteStepProps> = ({ onContinue, updateHeaderConte
</Grid>
</Card>
{/* No Website Button */}
<Box sx={{ mt: 2, textAlign: 'center', mb: 3 }}>
<Button
variant="outlined"
color="secondary"
onClick={() => {
console.log('🔄 Switching to business description form...');
setShowBusinessForm(true);
}}
startIcon={<BusinessIcon />}
disabled={loading}
>
Don't have a website?
</Button>
</Box>
{loading && (
<Card sx={{ mb: 3, p: 3 }}>
<Typography variant="h6" gutterBottom>