- {activeView ? : }
+ {activeView ? : }
-
+
{showEmptyScreen ? (
@@ -109,14 +142,12 @@ export function Chat({ id }: ChatProps) {
);
}
- // Desktop layout
return (
-
{/* Add Provider */}
+
- {/* This is the new div for scrolling */}
-
+
{showEmptyScreen ? (
{
@@ -129,9 +160,9 @@ export function Chat({ id }: ChatProps) {
- {activeView ? : }
+ {activeView ? : }
diff --git a/components/history-item.tsx b/components/history-item.tsx
index 4040e3f8..52203945 100644
--- a/components/history-item.tsx
+++ b/components/history-item.tsx
@@ -3,11 +3,11 @@
import React from 'react'
import Link from 'next/link'
import { usePathname } from 'next/navigation'
-import type { Chat as DrizzleChat } from '@/lib/actions/chat-db';
+import { type Chat } from '@/lib/types';
import { cn } from '@/lib/utils'
type HistoryItemProps = {
- chat: DrizzleChat & { path: string };
+ chat: Chat & { path: string };
}
const formatDateWithTime = (date: Date | string) => {
diff --git a/components/history-list.tsx b/components/history-list.tsx
index 5713bd2e..1943ff82 100644
--- a/components/history-list.tsx
+++ b/components/history-list.tsx
@@ -2,31 +2,13 @@ import React, { cache } from 'react';
import HistoryItem from './history-item';
import { ClearHistory } from './clear-history';
import { getChats } from '@/lib/actions/chat';
-
-// Define the type for the chat data returned by getChats
-type ChatData = {
- userId: string;
- id: string;
- title: string;
- createdAt: Date;
- visibility: string | null;
-};
-
-// Define the Chat type expected by HistoryItem
-type Chat = {
- userId: string;
- id: string;
- title: string;
- createdAt: Date;
- visibility: string | null;
- path: string;
-};
+import { type Chat } from '@/lib/types';
type HistoryListProps = {
userId?: string;
};
-const loadChats = cache(async (userId?: string): Promise => {
+const loadChats = cache(async (userId?: string): Promise => {
return await getChats(userId);
});
@@ -52,12 +34,12 @@ export async function HistoryList({ userId }: HistoryListProps) {
No search history
) : (
- chats.map((chat: ChatData) => (
+ chats.map((chat: Chat) => (
))
diff --git a/components/settings/components/settings.tsx b/components/settings/components/settings.tsx
index a4cc0ec9..be9eccaa 100644
--- a/components/settings/components/settings.tsx
+++ b/components/settings/components/settings.tsx
@@ -10,15 +10,13 @@ import { Button } from "@/components/ui/button"
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from "@/components/ui/card"
import { FormProvider, UseFormReturn } from "react-hook-form"; import React from "react";
import { Loader2, Save, RotateCcw } from "lucide-react"
-// Or, if the file does not exist, create it as shown below.
import { SystemPromptForm } from "./system-prompt-form"
import { ModelSelectionForm } from "./model-selection-form"
import { UserManagementForm } from './user-management-form';
import { Form } from "@/components/ui/form"
import { useToast } from "@/components/ui/hooks/use-toast"
-import { getSystemPrompt, saveSystemPrompt } from "../../../lib/actions/chat" // Added import
+import { getSystemPrompt, saveSystemPrompt } from "../../../lib/actions/chat"
-// Define the form schema
const settingsFormSchema = z.object({
systemPrompt: z
.string()
@@ -35,31 +33,28 @@ const settingsFormSchema = z.object({
z.object({
id: z.string(),
email: z.string().email(),
- role: z.enum(["admin", "editor", "viewer"]),
+ role: z.enum(["owner", "collaborator"]),
}),
),
newUserEmail: z.string().email().optional(),
- newUserRole: z.enum(["admin", "editor", "viewer"]).optional(),
+ newUserRole: z.enum(["owner", "collaborator"]).optional(),
})
export type SettingsFormValues = z.infer
-// Default values
const defaultValues: Partial = {
systemPrompt:
"You are a planetary copilot, an AI assistant designed to help users with information about planets, space exploration, and astronomy. Provide accurate, educational, and engaging responses about our solar system and beyond.",
selectedModel: "gpt-4o",
- users: [
- { id: "1", email: "admin@example.com", role: "admin" },
- { id: "2", email: "user@example.com", role: "editor" },
- ],
+ users: [],
}
interface SettingsProps {
initialTab?: string;
+ chatId: string;
}
-export function Settings({ initialTab = "system-prompt" }: SettingsProps) {
+export function Settings({ initialTab = "system-prompt", chatId }: SettingsProps) {
const { toast } = useToast()
const router = useRouter()
const [isLoading, setIsLoading] = useState(false)
@@ -69,7 +64,6 @@ export function Settings({ initialTab = "system-prompt" }: SettingsProps) {
setCurrentTab(initialTab);
}, [initialTab]);
- // TODO: Replace 'anonymous' with actual user ID from session/auth context
const userId = 'anonymous';
const form = useForm({
@@ -91,27 +85,21 @@ export function Settings({ initialTab = "system-prompt" }: SettingsProps) {
setIsLoading(true)
try {
- // Save the system prompt
const saveResult = await saveSystemPrompt(userId, data.systemPrompt);
if (saveResult?.error) {
throw new Error(saveResult.error);
}
- // Simulate other API calls if necessary or remove if only saving system prompt for this form
- await new Promise((resolve) => setTimeout(resolve, 200)) // Shorter delay now
+ await new Promise((resolve) => setTimeout(resolve, 200))
console.log("Submitted data (including system prompt):", data)
- // Success notification
toast({
title: "Settings updated",
description: "Your settings have been saved successfully.",
})
- // Refresh the page to reflect changes
- // router.refresh(); // Consider if refresh is needed or if optimistic update is enough
} catch (error: any) {
- // Error notification
toast({
title: "Something went wrong",
description: error.message || "Your settings could not be saved. Please try again.",
@@ -166,7 +154,7 @@ export function Settings({ initialTab = "system-prompt" }: SettingsProps) {
-
+
diff --git a/components/settings/components/user-management-form.tsx b/components/settings/components/user-management-form.tsx
index 2f9521df..79ee6106 100644
--- a/components/settings/components/user-management-form.tsx
+++ b/components/settings/components/user-management-form.tsx
@@ -9,14 +9,15 @@ import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@
import { FormField, FormItem, FormLabel, FormControl, FormMessage } from "@/components/ui/form";
import { Trash2, Edit3, UserPlus, Loader2 } from 'lucide-react';
import { useToast } from '@/components/ui/hooks/use-toast';
-import { addUser } from '@/lib/actions/users';
+import { inviteUserToChat } from '@/lib/actions/collaboration';
import type { SettingsFormValues } from './settings';
interface UserManagementFormProps {
form: UseFormReturn;
+ chatId: string;
}
-export function UserManagementForm({ form }: UserManagementFormProps) {
+export function UserManagementForm({ form, chatId }: UserManagementFormProps) {
const { fields, append, remove } = useFieldArray({
control: form.control,
name: "users",
@@ -24,15 +25,10 @@ export function UserManagementForm({ form }: UserManagementFormProps) {
const { toast } = useToast();
const [isAddingUser, setIsAddingUser] = useState(false);
- // const watchNewUserEmail = form.watch("newUserEmail", ""); // Not strictly needed for logic below
- // const watchNewUserRole = form.watch("newUserRole", "viewer"); // Not strictly needed for logic below
-
const handleAddUser = async () => {
setIsAddingUser(true);
const newUserEmail = form.getValues("newUserEmail");
- const newUserRole = form.getValues("newUserRole") || "viewer"; // Ensure role has a default
- // Client-side validation first
if (!newUserEmail) {
form.setError("newUserEmail", { type: "manual", message: "Email is required." });
setIsAddingUser(false);
@@ -43,27 +39,22 @@ export function UserManagementForm({ form }: UserManagementFormProps) {
setIsAddingUser(false);
return;
}
- // Client-side check if user already exists in the local list
- if (fields.some(user => user.email === newUserEmail)) {
- form.setError("newUserEmail", { type: "manual", message: "User with this email already exists locally." });
- setIsAddingUser(false);
- return;
- }
- // Clear any previous local errors for newUserEmail if client checks pass
+
form.clearErrors("newUserEmail");
try {
- const result = await addUser('default-user', { email: newUserEmail, role: newUserRole });
+ const result = await inviteUserToChat(chatId, newUserEmail);
if (result.error) {
toast({ title: 'Error adding user', description: result.error, variant: 'destructive' });
- form.setError("newUserEmail", { type: "manual", message: result.error }); // Show server error on field
- } else if (result.user) {
- toast({ title: 'User Added', description: `${result.user.email} was successfully added.` });
- append(result.user); // Add user with ID from server
+ form.setError("newUserEmail", { type: "manual", message: result.error });
+ } else {
+ toast({ title: 'User Invited', description: `${newUserEmail} was successfully invited.` });
+ // We don't append here because the user needs to accept the invite.
+ // We can add a "pending invitations" section in the future.
form.resetField("newUserEmail");
- form.resetField("newUserRole"); // Or set to default: form.setValue("newUserRole", "viewer");
- form.clearErrors("newUserEmail"); // Clear any previous errors
+ form.resetField("newUserRole");
+ form.clearErrors("newUserEmail");
}
} catch (error) {
console.error("Failed to add user:", error);
@@ -77,7 +68,7 @@ export function UserManagementForm({ form }: UserManagementFormProps) {
User Management
- Add, remove, or edit user access and roles.
+ Invite users to collaborate on this chat.
@@ -99,7 +90,7 @@ export function UserManagementForm({ form }: UserManagementFormProps) {
(
Role
@@ -110,9 +101,8 @@ export function UserManagementForm({ form }: UserManagementFormProps) {
- Admin
- Editor
- Viewer
+ Owner
+ Collaborator
@@ -122,7 +112,7 @@ export function UserManagementForm({ form }: UserManagementFormProps) {
diff --git a/components/settings/settings-view.tsx b/components/settings/settings-view.tsx
index 5f9e16ff..a5cb815a 100644
--- a/components/settings/settings-view.tsx
+++ b/components/settings/settings-view.tsx
@@ -5,7 +5,7 @@ import { useProfileToggle, ProfileToggleEnum } from "@/components/profile-toggle
import { Button } from "@/components/ui/button"
import { Minus } from "lucide-react"
-export default function SettingsView() {
+export default function SettingsView({ chatId }: { chatId: string }) {
const { toggleProfileSection, activeView } = useProfileToggle();
const initialTab = activeView === ProfileToggleEnum.Security ? "user-management" : "system-prompt";
@@ -28,7 +28,7 @@ export default function SettingsView() {