closes #8
This commit is contained in:
@@ -1,7 +1,8 @@
|
||||
import axios from 'axios';
|
||||
import Cookies from 'js-cookie';
|
||||
import { features } from './config/features';
|
||||
|
||||
const baseURL = import.meta.env.VITE_API_URL;
|
||||
const baseURL = features.apiUrl;
|
||||
console.log(baseURL);
|
||||
|
||||
export const axiosRealEstateApi = axios.create({
|
||||
|
||||
@@ -27,6 +27,7 @@ import {
|
||||
import { test_property_search } from 'data/mock_property_search';
|
||||
import { extractLatLon } from 'utils';
|
||||
import { test_autocomplete } from 'data/mock_autocomplete_results';
|
||||
import { features } from '../../../../../config/features';
|
||||
|
||||
interface AddPropertyDialogProps {
|
||||
open: boolean;
|
||||
@@ -204,7 +205,7 @@ const AddPropertyDialog: React.FC<AddPropertyDialogProps> = ({ open, onClose, on
|
||||
console.log('here we go', value);
|
||||
if (value) {
|
||||
console.log('find the test data');
|
||||
const test: boolean = import.meta.env.USE_LIVE_DATA;
|
||||
const test: boolean = features.useLiveData;
|
||||
if (test) {
|
||||
const parts: string[] =
|
||||
test_property_search.data.currentMortgages[0].recordingDate.split('T');
|
||||
|
||||
@@ -25,6 +25,7 @@ import { PlacePrediction } from './AddPropertyDialog';
|
||||
import { test_autocomplete } from 'data/mock_autocomplete_results';
|
||||
import { axiosInstance, axiosRealEstateApi } from '../../../../../axiosApi';
|
||||
import { extractLatLon } from 'utils';
|
||||
import { features } from '../../../../../config/features';
|
||||
|
||||
interface AttorneyProfileCardProps {
|
||||
attorney: AttorneyAPI;
|
||||
@@ -115,7 +116,7 @@ const AttorneyProfileCard: React.FC<AttorneyProfileCardProps> = ({
|
||||
event: React.SyntheticEvent,
|
||||
value: string,
|
||||
) => {
|
||||
const test: boolean = !import.meta.env.USE_LIVE_DATA;
|
||||
const test: boolean = !features.useLiveData;
|
||||
let data: AutocompleteDataResponseAPI[] = [];
|
||||
if (value.length > 2) {
|
||||
if (test) {
|
||||
|
||||
57
ditch-the-agent/src/config/features.ts
Normal file
57
ditch-the-agent/src/config/features.ts
Normal file
@@ -0,0 +1,57 @@
|
||||
/**
|
||||
* Feature flags and environment configuration
|
||||
* Controls feature availability and environment settings based on build mode (production, beta, development)
|
||||
*/
|
||||
|
||||
interface FeatureConfig {
|
||||
// Registration features
|
||||
enableAttorneyRegistration: boolean;
|
||||
enableRealEstateAgentRegistration: boolean;
|
||||
enableRegistration: boolean;
|
||||
|
||||
// API Configuration
|
||||
apiUrl: string;
|
||||
|
||||
// Data Configuration
|
||||
useLiveData: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get feature configuration based on current environment
|
||||
*/
|
||||
const getFeatureConfig = (): FeatureConfig => {
|
||||
const mode = import.meta.env.MODE || 'development';
|
||||
|
||||
// Production configuration
|
||||
if (mode === 'production') {
|
||||
return {
|
||||
enableAttorneyRegistration: false,
|
||||
enableRealEstateAgentRegistration: false,
|
||||
enableRegistration: false,
|
||||
apiUrl: 'https://backend.ditchtheagent.com/api/',
|
||||
useLiveData: true,
|
||||
};
|
||||
}
|
||||
|
||||
// Beta configuration
|
||||
if (mode === 'beta') {
|
||||
return {
|
||||
enableAttorneyRegistration: true,
|
||||
enableRealEstateAgentRegistration: true,
|
||||
enableRegistration: true,
|
||||
apiUrl: 'https://beta.backend.ditchtheagent.com/api/',
|
||||
useLiveData: true,
|
||||
};
|
||||
}
|
||||
|
||||
// Development configuration (default)
|
||||
return {
|
||||
enableAttorneyRegistration: true,
|
||||
enableRealEstateAgentRegistration: true,
|
||||
enableRegistration: true,
|
||||
apiUrl: 'http://127.0.0.1:8010/api/',
|
||||
useLiveData: false,
|
||||
};
|
||||
};
|
||||
|
||||
export const features = getFeatureConfig();
|
||||
@@ -1,6 +1,7 @@
|
||||
import React, { useEffect, createContext, useRef, useState, useContext, ReactNode } from 'react';
|
||||
import { AccountContext } from './AccountContext';
|
||||
import { AuthContext } from './AuthContext';
|
||||
import { features } from '../config/features';
|
||||
|
||||
// ---
|
||||
// Define Types and Interfaces
|
||||
@@ -65,10 +66,10 @@ interface WebSocketProviderProps {
|
||||
// Provide a default value that matches the IWebSocketContext interface.
|
||||
// This is used when a component tries to consume the context without a provider.
|
||||
const WebSocketContext = createContext<IWebSocketContext>({
|
||||
subscribe: () => {},
|
||||
unsubscribe: () => {},
|
||||
subscribe: () => { },
|
||||
unsubscribe: () => { },
|
||||
socket: null,
|
||||
sendMessages: () => {},
|
||||
sendMessages: () => { },
|
||||
});
|
||||
|
||||
// ---
|
||||
@@ -141,7 +142,7 @@ function WebSocketProvider({ children }: WebSocketProviderProps) {
|
||||
ws.current.close();
|
||||
}
|
||||
|
||||
const wsUrl = new URL(import.meta.env.VITE_API_URL || 'ws://127.0.0.1:8010/ws/');
|
||||
const wsUrl = new URL(features.apiUrl || 'ws://127.0.0.1:8010/ws/');
|
||||
wsUrl.protocol = wsUrl.protocol.replace('http', 'ws');
|
||||
|
||||
ws.current = new WebSocket(
|
||||
|
||||
@@ -20,8 +20,9 @@ import {
|
||||
Switch,
|
||||
Typography,
|
||||
} from '@mui/material';
|
||||
import { features } from '../../config/features';
|
||||
|
||||
const base_url: string = `${import.meta.env.VITE_API_URL?.replace('/api/', '')}/media/vendor_pictures/`;
|
||||
const base_url: string = `${features.apiUrl?.replace('/api/', '')}/media/vendor_pictures/`;
|
||||
|
||||
// Define the array of corrected and alphabetized categories with 'as const'
|
||||
export const CATEGORY_NAMES = [
|
||||
|
||||
@@ -24,6 +24,7 @@ import Image from 'components/base/Image';
|
||||
import { axiosInstance } from '../../axiosApi.js';
|
||||
import PasswordStrengthChecker from '../../components/PasswordStrengthChecker';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { features } from '../../config/features';
|
||||
|
||||
type SignUpValues = {
|
||||
email: string;
|
||||
@@ -191,41 +192,43 @@ const SignUp = (): ReactElement => {
|
||||
</InputLabel>
|
||||
<Stack direction={{ xs: 'column', sm: 'row' }} spacing={2}>
|
||||
{[
|
||||
{ value: 'property_owner', label: 'Home Buyer/Seller', icon: 'mdi:home-account' },
|
||||
{ value: 'attorney', label: 'Attorney', icon: 'mdi:gavel' },
|
||||
{ value: 'vendor', label: 'Vendor', icon: 'mdi:briefcase' },
|
||||
].map((type) => (
|
||||
<Paper
|
||||
key={type.value}
|
||||
variant="outlined"
|
||||
onClick={() => setFieldValue('ownerType', type.value)}
|
||||
sx={{
|
||||
p: 2,
|
||||
flex: 1,
|
||||
cursor: 'pointer',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
alignItems: 'center',
|
||||
gap: 1,
|
||||
borderColor: values.ownerType === type.value ? 'primary.main' : 'divider',
|
||||
bgcolor: values.ownerType === type.value ? 'action.selected' : 'background.paper',
|
||||
transition: 'all 0.2s',
|
||||
'&:hover': {
|
||||
borderColor: 'primary.main',
|
||||
bgcolor: 'action.hover',
|
||||
},
|
||||
}}
|
||||
>
|
||||
<IconifyIcon icon={type.icon} width={24} height={24} color={values.ownerType === type.value ? 'primary.main' : 'text.secondary'} />
|
||||
<Typography
|
||||
variant="body2"
|
||||
fontWeight={600}
|
||||
color={values.ownerType === type.value ? 'primary.main' : 'text.primary'}
|
||||
{ value: 'property_owner', label: 'Home Buyer/Seller', icon: 'mdi:home-account', enabled: true },
|
||||
{ value: 'attorney', label: 'Attorney', icon: 'mdi:gavel', enabled: features.enableAttorneyRegistration },
|
||||
{ value: 'vendor', label: 'Vendor', icon: 'mdi:briefcase', enabled: features.enableRealEstateAgentRegistration },
|
||||
]
|
||||
.filter((type) => type.enabled)
|
||||
.map((type) => (
|
||||
<Paper
|
||||
key={type.value}
|
||||
variant="outlined"
|
||||
onClick={() => setFieldValue('ownerType', type.value)}
|
||||
sx={{
|
||||
p: 2,
|
||||
flex: 1,
|
||||
cursor: 'pointer',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
alignItems: 'center',
|
||||
gap: 1,
|
||||
borderColor: values.ownerType === type.value ? 'primary.main' : 'divider',
|
||||
bgcolor: values.ownerType === type.value ? 'action.selected' : 'background.paper',
|
||||
transition: 'all 0.2s',
|
||||
'&:hover': {
|
||||
borderColor: 'primary.main',
|
||||
bgcolor: 'action.hover',
|
||||
},
|
||||
}}
|
||||
>
|
||||
{type.label}
|
||||
</Typography>
|
||||
</Paper>
|
||||
))}
|
||||
<IconifyIcon icon={type.icon} width={24} height={24} color={values.ownerType === type.value ? 'primary.main' : 'text.secondary'} />
|
||||
<Typography
|
||||
variant="body2"
|
||||
fontWeight={600}
|
||||
color={values.ownerType === type.value ? 'primary.main' : 'text.primary'}
|
||||
>
|
||||
{type.label}
|
||||
</Typography>
|
||||
</Paper>
|
||||
))}
|
||||
</Stack>
|
||||
</FormControl>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user