Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
26 changes: 19 additions & 7 deletions frontend/src/app/(main)/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,15 @@ import { useAuthContext } from '@/providers/AuthProvider';
import { ProjectsSection } from '@/components/root/projects-section';
import { PromptForm, PromptFormRef } from '@/components/root/prompt-form';
import { ProjectContext } from '@/components/chat/code-engine/project-context';

import { SignInModal } from '@/components/sign-in-modal';
import { SignUpModal } from '@/components/sign-up-modal';
import { useRouter } from 'next/navigation';
export default function HomePage() {
// States for AuthChoiceModal
const [showAuthChoice, setShowAuthChoice] = useState(false);
const router = useRouter();
const [showSignIn, setShowSignIn] = useState(false);
const [showSignUp, setShowSignUp] = useState(false);

const promptFormRef = useRef<PromptFormRef>(null);
const { isAuthorized } = useAuthContext();
Expand All @@ -19,9 +25,7 @@ export default function HomePage() {
const handleSubmit = async () => {
if (!promptFormRef.current) return;

// Get form data from the prompt form
const { message, isPublic, model } = promptFormRef.current.getPromptData();

if (!message.trim()) return;

try {
Expand All @@ -37,12 +41,11 @@ export default function HomePage() {
}
} catch (error) {
console.error('Error creating project:', error);
// Error handling is done via toast in ProjectContext
}
};

return (
<div className="pt-32 pb-24 px-6 ">
<div className="pt-32 pb-24 px-6">
<motion.div
className="flex flex-col items-center"
initial={{ opacity: 0, y: 20 }}
Expand Down Expand Up @@ -85,19 +88,28 @@ export default function HomePage() {
</div>
</motion.div>

{/* Modals */}
{/* Choice Modal */}
<AuthChoiceModal
isOpen={showAuthChoice}
onClose={() => setShowAuthChoice(false)}
onSignUpClick={() => {
setShowAuthChoice(false);
setTimeout(() => {
setShowSignUp(true);
}, 100);
}}
onSignInClick={() => {
setShowAuthChoice(false);
setTimeout(() => {
setShowSignIn(true);
}, 100);
}}
/>

{/* Add this to your global CSS for the subtle pulse animation */}
{/* SignInModal & SignUpModal */}
<SignInModal isOpen={showSignIn} onClose={() => setShowSignIn(false)} />
<SignUpModal isOpen={showSignUp} onClose={() => setShowSignUp(false)} />

<style jsx global>{`
.animate-pulse-subtle {
animation: pulse-subtle 2s infinite;
Expand Down
21 changes: 19 additions & 2 deletions frontend/src/components/auth-choice-modal.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
'use client';

import { Dialog, DialogContent, DialogTitle } from '@/components/ui/dialog';
import { BackgroundGradient } from '@/components/ui/background-gradient';
import { Button } from '@/components/ui/button';
Expand All @@ -24,6 +25,7 @@ export function AuthChoiceModal({
<VisuallyHidden>
<DialogTitle>Choose Authentication Method</DialogTitle>
</VisuallyHidden>

<BackgroundGradient className="rounded-[22px] p-4 bg-white dark:bg-zinc-900">
<div className="w-full p-6 space-y-6">
<h2 className="text-2xl font-semibold text-center dark:text-white">
Expand All @@ -33,16 +35,31 @@ export function AuthChoiceModal({
Choose how you want to continue
</p>
<div className="space-y-4">
{/* Sign In button */}
<Button
className="w-full py-6 text-lg bg-primary hover:bg-primary/90"
onClick={onSignInClick}
onClick={() => {
// 1) Close current modal
onClose();
// 2) After a brief delay, call onSignInClick
setTimeout(() => {
onSignInClick();
}, 100);
}}
>
Sign in
</Button>

{/* Sign Up button */}
<Button
variant="outline"
className="w-full py-6 text-lg"
onClick={onSignUpClick}
onClick={() => {
onClose();
setTimeout(() => {
onSignUpClick();
}, 100);
}}
>
Create an account
</Button>
Expand Down
4 changes: 3 additions & 1 deletion frontend/src/components/chat/chat-layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ export default function ChatLayout({
const { isAuthorized } = useAuthContext();
const [isModalOpen, setIsModalOpen] = useState(false);

const { refetch } = useQuery(GET_USER_PROJECTS);
const { refetch } = useQuery(GET_USER_PROJECTS, {
skip: !isAuthorized,
});
const router = useRouter();

useEffect(() => {
Expand Down
4 changes: 3 additions & 1 deletion frontend/src/components/chat/code-engine/project-context.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import {
import { Project } from '../project-modal';
import { useRouter } from 'next/navigation';
import { toast } from 'sonner'; // Assuming you use Sonner for toasts
import { useAuthContext } from '@/providers/AuthProvider';

export interface ProjectContextType {
projects: Project[];
Expand Down Expand Up @@ -48,7 +49,7 @@ export const ProjectContext = createContext<ProjectContextType | undefined>(

export function ProjectProvider({ children }: { children: ReactNode }) {
const router = useRouter();

const { isAuthorized } = useAuthContext();
const [projects, setProjects] = useState<Project[]>([]);
const [curProject, setCurProject] = useState<Project | undefined>(undefined);
const [filePath, setFilePath] = useState<string | null>(null);
Expand Down Expand Up @@ -85,6 +86,7 @@ export function ProjectProvider({ children }: { children: ReactNode }) {

const { loading, error, refetch } = useQuery(GET_USER_PROJECTS, {
fetchPolicy: 'network-only',
skip: !isAuthorized,
onCompleted: (data) => {
setProjects(data.getUserProjects);
// If we have a current project in the list, update it
Expand Down
3 changes: 3 additions & 0 deletions frontend/src/components/chat/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,11 @@ import { useChatStream } from '@/hooks/useChatStream';
import { CodeEngine } from './code-engine/code-engine';
import { useProjectStatusMonitor } from '@/hooks/useProjectStatusMonitor';
import { Loader2 } from 'lucide-react';
import { useAuthContext } from '@/providers/AuthProvider';

export default function Chat() {
// Initialize state, refs, and custom hooks
const { isAuthorized } = useAuthContext();
const urlParams = new URLSearchParams(window.location.search);
const [chatId, setChatId] = useState('');
const [messages, setMessages] = useState<any[]>([]);
Expand All @@ -36,6 +38,7 @@ export default function Chat() {
// Apollo query to fetch chat history
useQuery(GET_CHAT_HISTORY, {
variables: { chatId },
skip: !isAuthorized || !chatId,
onCompleted: (data) => {
if (data?.getChatHistory) {
setMessages(data.getChatHistory);
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/components/root/nav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -174,15 +174,15 @@ const FloatingNavbar = forwardRef<NavbarRef, FloatingNavbarProps>(
alert('Coming Soon');
} else if (label === 'Codefox Journey') {
e.preventDefault();
window.open('https://github.com/Sma1lboy/codefox', '_blank');
alert('Coming Soon');
} else {
handleTabChange(index);
}
};

return (
<>
<div className={`fixed top-5 left-0 right-0 z-50 ${className}`}>
<div className={` top-5 left-0 right-0 z-50 ${className}`}>
<motion.div
className={`w-full flex justify-around items-center px-6 py-4 ${containerClassName}`}
initial="hidden"
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/root/prompt-form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ export const PromptForm = forwardRef<PromptFormRef, PromptFormProps>(
>
<SelectTrigger
className={cn(
'w-[117px] h-6 border-0 focus:ring-0 hover:bg-gray-100 dark:hover:bg-gray-600 pl-1',
'h-6 border-0 focus:ring-0 hover:bg-gray-100 dark:hover:bg-gray-600 pl-1 min-w-max',
(isLoading || isRegenerating) &&
'opacity-50 cursor-not-allowed'
)}
Expand Down
38 changes: 26 additions & 12 deletions frontend/src/components/sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import UserSettings from './user-settings';
import { SideBarItem } from './sidebar-item';
import { Chat } from '@/graphql/type';
import { EventEnum } from '../const/EventEnum';
import { useRouter } from 'next/navigation';

import {
SidebarContent,
Expand Down Expand Up @@ -48,6 +49,7 @@ export function ChatSideBar({
onRefetch,
}: SidebarProps) {
// Use a local state only for the currently selected chat.
const router = useRouter();
const [currentChatid, setCurrentChatid] = useState('');
const { setCurProject, pollChatProject } = useContext(ProjectContext);
// Handler for starting a new chat.
Expand All @@ -57,20 +59,12 @@ export function ChatSideBar({
const event = new Event(EventEnum.NEW_CHAT);
window.dispatchEvent(event);
}, []);

if (loading) return <SidebarSkeleton />;
if (error) {
console.error('Error loading chats:', error);
return null;
}

console.log(
'ChatSideBar state: isCollapsed:',
isCollapsed,
'currentChatid:',
currentChatid
);

return (
<div
data-collapsed={isCollapsed}
Expand All @@ -82,8 +76,27 @@ export function ChatSideBar({
className="lg:flex items-center justify-center cursor-pointer p-2 ml-3.5 mt-2"
onClick={() => setIsCollapsed(!isCollapsed)}
/>

<div className="flex items-center justify-start w-[85%] h-14 text-sm xl:text-lg font-normal pl-4 gap-2">
<Button
onClick={() => router.push('/')}
variant="ghost"
className="
w-full
h-14
flex
items-center
justify-start
px-4
gap-2
text-sm
xl:text-lg
font-normal
rounded-md
hover:bg-yellow-50
transition-all
duration-200
ease-in-out
"
>
<Image
src="/codefox.svg"
alt="CodeFox Logo"
Expand All @@ -96,9 +109,10 @@ export function ChatSideBar({
CodeFox
</span>
)}
</div>
</Button>

{/* Divider Line */}
<div className="border-t border-dotted border-gray-300 my-2 w-[85%] mx-auto"></div>
<div className="border-t border-dotted border-gray-300 my-2 w-full mx-auto" />

<Button
onClick={() => setIsModalOpen(true)}
Expand Down
4 changes: 3 additions & 1 deletion frontend/src/components/sign-in-modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,9 @@ export function SignInModal({ isOpen, onClose }: SignInModalProps) {
if (data?.login) {
// Store tokens where desired (session storage for access, local for refresh)
login(data.login.accessToken, data.login.refreshToken);
toast.success('Login successful!');
toast.success('Login successful!', {
position: 'bottom-right',
});
setErrorMessage(null);
onClose(); // Close the modal

Expand Down
6 changes: 2 additions & 4 deletions frontend/src/graphql/schema.gql
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,7 @@ input CreateProjectInput {
public: Boolean
}

"""
Date custom scalar type
"""
"""Date custom scalar type"""
scalar Date

input FetchPublicProjectsInputs {
Expand Down Expand Up @@ -221,4 +219,4 @@ type User {
subscribedProjects: [Project!] @deprecated(reason: "Use projects with forkedFromId instead")
updatedAt: Date!
username: String!
}
}
4 changes: 3 additions & 1 deletion frontend/src/hooks/useChatList.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,19 @@ import { useQuery } from '@apollo/client';
import { GET_USER_CHATS } from '@/graphql/request';
import { Chat } from '@/graphql/type';
import { useState, useCallback, useMemo } from 'react';
import { useAuthContext } from '@/providers/AuthProvider';

export function useChatList() {
const [chatListUpdated, setChatListUpdated] = useState(false);

const { isAuthorized } = useAuthContext();
const {
data: chatData,
loading,
error,
refetch,
} = useQuery<{ getUserChats: Chat[] }>(GET_USER_CHATS, {
fetchPolicy: chatListUpdated ? 'network-only' : 'cache-first',
skip: !isAuthorized,
});

const handleRefetch = useCallback(() => {
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/hooks/useModels.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ interface ModelsCache {
models: string[];
lastUpdate: number;
}

const CACHE_DURATION = 30 * 60 * 1000;
export const useModels = () => {
const { isAuthorized } = useAuthContext();
const [selectedModel, setSelectedModel] = useState<string | undefined>(
undefined
);
Expand Down Expand Up @@ -50,7 +50,7 @@ export const useModels = () => {
const { data, loading, error } = useQuery<{
getAvailableModelTags: string[];
}>(GET_MODEL_TAGS, {
skip: !shouldUpdateCache(),
skip: !isAuthorized || !shouldUpdateCache(),
onCompleted: (data) => {
console.log(data);
if (data?.getAvailableModelTags) {
Expand Down
Loading
Loading