diff --git a/Dockerfile b/Dockerfile index e7c2c3d..d2aade3 100644 --- a/Dockerfile +++ b/Dockerfile @@ -13,6 +13,12 @@ RUN npm ci # Copy all files COPY . . +# Copy .env file if it exists +COPY .env* ./ + +# Print environment for debugging (will be removed in production) +RUN if [ -f .env ]; then cat .env; fi + # Build the app RUN npm run build diff --git a/cloudbuild.yaml b/cloudbuild.yaml index cfa1221..23c1aa8 100644 --- a/cloudbuild.yaml +++ b/cloudbuild.yaml @@ -1,5 +1,16 @@ steps: - # Build the container image + # Access secrets and create a .env file for the build + - name: 'gcr.io/cloud-builders/gcloud' + entrypoint: 'bash' + args: + - '-c' + - | + gcloud secrets versions access latest --secret=GOOGLE_CLIENT_ID > /workspace/google_client_id.txt + echo "VITE_GOOGLE_CLIENT_ID=$(cat /workspace/google_client_id.txt)" > /workspace/.env + echo "VITE_API_URL=${_VITE_API_URL}" >> /workspace/.env + cat /workspace/.env + + # Build the container image with access to the .env file - name: 'gcr.io/cloud-builders/docker' args: ['build', '-t', '${_REGION}-docker.pkg.dev/${PROJECT_ID}/${_REPOSITORY}/${_IMAGE_NAME}', '.'] env: diff --git a/index.html b/index.html index bb33833..37c4498 100644 --- a/index.html +++ b/index.html @@ -4,9 +4,11 @@ MindGarden + +
- \ No newline at end of file + \ No newline at end of file diff --git a/public/env-check.js b/public/env-check.js new file mode 100644 index 0000000..14d3fbe --- /dev/null +++ b/public/env-check.js @@ -0,0 +1,29 @@ +// This script runs in the browser and logs environment variable status +console.log('Environment Check Script Running'); +console.log('VITE_GOOGLE_CLIENT_ID available:', !!window.ENV_CONFIG?.GOOGLE_CLIENT_ID || 'Not available through window.ENV_CONFIG'); + +// Create a global object to store runtime environment information +window.ENV_DEBUG = { + checkTime: new Date().toISOString(), + checkEnvironment: function() { + console.log('=== Environment Debug Information ==='); + console.log('Check Time:', this.checkTime); + console.log('window.ENV_CONFIG:', window.ENV_CONFIG || 'Not defined'); + + // This will be replaced at build time by Vite + const viteBuildTimeValue = '__VITE_GOOGLE_CLIENT_ID_PLACEHOLDER__'; + console.log('Vite Build-time Client ID available:', + viteBuildTimeValue !== '__VITE_GOOGLE_CLIENT_ID_PLACEHOLDER__' ? 'Yes' : 'No'); + + return { + checkTime: this.checkTime, + hasEnvConfig: !!window.ENV_CONFIG, + hasBuildTimeValue: viteBuildTimeValue !== '__VITE_GOOGLE_CLIENT_ID_PLACEHOLDER__' + }; + } +}; + +// Run the check automatically +document.addEventListener('DOMContentLoaded', () => { + window.ENV_DEBUG.checkEnvironment(); +}); diff --git a/src/components/ChatInterface.tsx b/src/components/ChatInterface.tsx index ad1d43a..5dc2fd3 100644 --- a/src/components/ChatInterface.tsx +++ b/src/components/ChatInterface.tsx @@ -11,21 +11,45 @@ interface Message { } const ChatInterface: React.FC = () => { - const { user, isAuthenticated, logout } = useAuth() + const { user, isAuthenticated } = useAuth() - // Create welcome message based on authentication status - const welcomeMessage = user?.name - ? `Hello ${user.name}! I'm here to support you. How are you feeling today?` - : 'Hello! I\'m here to support you. How are you feeling today?' + // Log authentication state for debugging purposes + useEffect(() => { + console.log('Auth state in ChatInterface:', { isAuthenticated, user }) + }, [isAuthenticated, user]) + + // Function to get welcome message based on current auth state + const getWelcomeMessage = () => { + return user?.name + ? `Hello ${user.name}! I'm here to support you. How are you feeling today?` + : 'Hello! I\'m here to support you. How are you feeling today?' + } + // Initialize messages with welcome message const [messages, setMessages] = useState([ { id: '1', - text: welcomeMessage, + text: getWelcomeMessage(), type: 'ai', timestamp: new Date() } ]) + + // Update first message when auth state changes + useEffect(() => { + setMessages(prevMessages => { + // Create a copy of the messages array + const updatedMessages = [...prevMessages] + // Update the first message if it exists + if (updatedMessages.length > 0) { + updatedMessages[0] = { + ...updatedMessages[0], + text: getWelcomeMessage() + } + } + return updatedMessages + }) + }, [user, isAuthenticated]) const [inputText, setInputText] = useState('') const [isTyping, setIsTyping] = useState(false) const messagesEndRef = useRef(null) @@ -149,16 +173,6 @@ const ChatInterface: React.FC = () => {

You're not alone

- {isAuthenticated && ( - - Logout - - )}

We're here to support and guide you through anything. diff --git a/src/components/TopNavigation.tsx b/src/components/TopNavigation.tsx index 733d907..f525716 100644 --- a/src/components/TopNavigation.tsx +++ b/src/components/TopNavigation.tsx @@ -1,17 +1,80 @@ -import React, { useState } from 'react' +import React, { useState, useEffect } from 'react' import { Link, useLocation } from 'react-router-dom' import { motion, AnimatePresence } from 'framer-motion' +import { useAuth } from '../contexts/AuthContext' + +// Define types for navigation items +interface BaseNavItem { + path: string + label: string + icon?: string + isEmergency?: boolean +} + +interface NavItemWithAction extends BaseNavItem { + onClick?: (e: React.MouseEvent) => void + disabled?: boolean +} + +type NavItem = BaseNavItem | NavItemWithAction const TopNavigation: React.FC = () => { const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false) const location = useLocation() + const { user, isAuthenticated, logout, isLoading } = useAuth() + + // State to track authentication status for UI rendering + const [authState, setAuthState] = useState({ + isUserAuthenticated: false, + userName: '' + }) + + // Effect to update local state when authentication changes + useEffect(() => { + console.log('Auth state changed in TopNavigation:', { isAuthenticated, user }) + setAuthState({ + isUserAuthenticated: isAuthenticated === true, + userName: user?.name || '' + }) + }, [isAuthenticated, user]) - const navItems = [ + // Basic navigation items that are always shown + const baseNavItems: BaseNavItem[] = [ { path: '/agents', label: 'Meet the Agents' }, { path: '/faq', label: 'FAQ' }, - { path: '/login', label: 'Login' }, ] + // Type guard function to check if a NavItem has onClick property + const hasOnClick = (item: NavItem): item is NavItemWithAction => { + return 'onClick' in item; + } + + // Type guard function to check if a NavItem has disabled property + const hasDisabled = (item: NavItem): item is NavItemWithAction => { + return 'disabled' in item; + } + + // Dynamically determine auth-related nav item + const getAuthNavItem = (): NavItemWithAction => { + if (isLoading) { + return { path: '#', label: 'Loading...', disabled: true } + } else if (authState.isUserAuthenticated) { + return { + path: '#', + label: `Logout (${authState.userName.split(' ')[0] || 'User'})`, + onClick: (e: React.MouseEvent) => { + e.preventDefault() + logout() + } + } + } else { + return { path: '/login', label: 'Login' } + } + } + + // Combine base items with auth item + const navItems: NavItem[] = [...baseNavItems, getAuthNavItem()] + const emergencyItem = { path: '/emergency', label: 'Emergency', icon: '🚨', isEmergency: true } const toggleMobileMenu = () => { @@ -37,22 +100,47 @@ const TopNavigation: React.FC = () => { {/* Desktop Navigation & Emergency Button */}

- {navItems.map((item) => ( - - {item.label} - - ))} + {navItems.map((item) => { + // For items with custom onClick handlers (like logout) + if (hasOnClick(item)) { + return ( + + ); + } + + // Regular link items + return ( + + {item.label} + + ); + })} { className="md:hidden border-t border-gray-200" >
- {navItems.map((item) => ( - setIsMobileMenuOpen(false)} - className={`flex items-center gap-3 px-4 py-3 rounded-xl transition-all duration-200 font-medium ${ - location.pathname === item.path - ? 'bg-gradient-to-r from-primary to-primary-dark text-white shadow-md' - : 'text-gray-600 hover:bg-gray-50 hover:text-gray-800' - }`} - > - {item.label} - - ))} + {navItems.map((item) => { + // For items with custom onClick handlers (like logout) + if (hasOnClick(item)) { + return ( + + ); + } + + // Regular link items + return ( + setIsMobileMenuOpen(false)} + className={`flex items-center gap-3 px-4 py-3 rounded-xl transition-all duration-200 font-medium ${ + location.pathname === item.path + ? 'bg-gradient-to-r from-primary to-primary-dark text-white shadow-md' + : 'text-gray-600 hover:bg-gray-50 hover:text-gray-800' + }`} + > + {item.label} + + ); + })} = ({ children }) => { const [user, setUser] = useState(null); @@ -223,8 +226,11 @@ export const AuthProvider: React.FC = ({ children }) => { // Remove default auth header delete axios.defaults.headers.common['Authorization']; + // Explicitly set user to null to trigger isAuthenticated update setUser(null); setIsGuest(false); + + console.log('Logout called, user state cleared'); }; // Compute authentication status diff --git a/src/main.tsx b/src/main.tsx index bcdeb23..9014a94 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -6,20 +6,35 @@ import App from './App.tsx' import { AuthProvider } from './contexts/AuthContext' import './index.css' -// Get Google Client ID from environment variable +// Get Google Client ID from environment variable with enhanced debugging const googleClientId = import.meta.env.VITE_GOOGLE_CLIENT_ID; -// Debug: Check if the client ID is loaded correctly -console.log('Google Client ID:', googleClientId ? 'ID is present' : 'ID is missing'); +// Debug: Check if the client ID is loaded correctly with detailed logging +console.log('Environment Variables Debug:') +console.log('- VITE_GOOGLE_CLIENT_ID:', googleClientId ? 'ID is present' : 'ID is missing'); +console.log('- All env variables available:', Object.keys(import.meta.env).join(', ')); + +// Create a fallback mechanism for development/testing without auth +const useGoogleAuth = googleClientId && googleClientId.length > 10; + +if (!useGoogleAuth) { + console.warn('⚠️ Google Client ID is missing or invalid! Authentication features will be limited.'); +} ReactDOM.createRoot(document.getElementById('root')!).render( - + {useGoogleAuth ? ( + + + + + + ) : ( - + )} - , + ) \ No newline at end of file diff --git a/src/pages/ChatPage.tsx b/src/pages/ChatPage.tsx index f8fddd0..947ce30 100644 --- a/src/pages/ChatPage.tsx +++ b/src/pages/ChatPage.tsx @@ -3,7 +3,7 @@ import ChatInterface from '../components/ChatInterface.tsx' const ChatPage: React.FC = () => { return ( -
+
)