Skip to content

Commit 69ab1f0

Browse files
Runtime Error
Error: Settings2 is not defined Call Stack 3 Hide 1 ig
1 parent 4a58142 commit 69ab1f0

1 file changed

Lines changed: 49 additions & 72 deletions

File tree

src/app/(app)/projects/[id]/page.tsx

Lines changed: 49 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { Card, CardContent, CardDescription, CardHeader, CardTitle, CardFooter }
77
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
88
import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar';
99
import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, AlertDialogTrigger } from "@/components/ui/alert-dialog";
10-
import { ArrowLeft, Edit3, PlusCircle, Trash2, CheckSquare, FileText, Megaphone, Users, FolderGit2, Loader2, Mail, UserX, Tag as TagIcon, BookOpen, Pin, PinOff, ShieldAlert, Eye as EyeIcon, Flame, AlertCircle, ListChecks, Palette, CheckCircle, ExternalLink, Info, Code2, Github, Link2, Unlink, Copy as CopyIcon, Terminal, InfoIcon, GitBranch, DownloadCloud, MessageSquare, FileCode, Edit, XCircle } from 'lucide-react';
10+
import { ArrowLeft, Edit3, PlusCircle, Trash2, CheckSquare, FileText, Megaphone, Users, FolderGit2, Loader2, Mail, UserX, Tag as TagIcon, BookOpen, Pin, PinOff, ShieldAlert, Eye as EyeIcon, Flame, AlertCircle, ListChecks, Palette, CheckCircle, ExternalLink, Info, Code2, Github, Link2, Unlink, Copy as CopyIcon, Terminal, InfoIcon, GitBranch, DownloadCloud, MessageSquare, FileCode, Edit, XCircle, Settings2 } from 'lucide-react';
1111
import Link from 'next/link';
1212
import type { Project, Task, Document as ProjectDocumentType, Tag as TagType, ProjectMember, ProjectMemberRole, TaskStatus, Announcement as ProjectAnnouncementType, UserGithubOAuthToken } from '@/types';
1313
import { Badge } from '@/components/ui/badge';
@@ -118,10 +118,10 @@ const linkGithubFormSchema = z.object({
118118
githubRepoName: z.string().optional(),
119119
useDefaultRepoName: z.boolean().default(true),
120120
}).refine(data => {
121-
if (!data.useDefaultRepoName) {
122-
return data.githubRepoName && data.githubRepoName.trim() !== '';
121+
if (!data.useDefaultRepoName) {
122+
return data.githubRepoName && data.githubRepoName.trim() !== '';
123123
}
124-
return true;
124+
return true;
125125
}, {
126126
message: "Custom repository name cannot be empty if not using the default.",
127127
path: ["githubRepoName"],
@@ -238,11 +238,11 @@ function ProjectDetailPageContent() {
238238
const oauthStatus = searchParams.get('oauth_status');
239239
if (oauthStatus === 'success') {
240240
toast({title: "GitHub Connected!", description: "Your GitHub account has been successfully linked."});
241-
loadUserGithubOAuth(); // Reload OAuth token state
241+
loadUserGithubOAuth();
242242
const newUrl = new URL(window.location.href);
243243
newUrl.searchParams.delete('oauth_status');
244-
newUrl.searchParams.delete('code'); // if GitHub adds it
245-
newUrl.searchParams.delete('state'); // if GitHub adds it
244+
newUrl.searchParams.delete('code');
245+
newUrl.searchParams.delete('state');
246246
router.replace(newUrl.toString(), { scroll: false });
247247
} else if (oauthStatus === 'error' || searchParams.get('error')) {
248248
toast({variant: "destructive", title: "GitHub Connection Error", description: searchParams.get('message') || searchParams.get('error_description') || "Failed to connect GitHub account."});
@@ -803,9 +803,6 @@ function ProjectDetailPageContent() {
803803
formData.append('projectUuid', project.uuid);
804804
formData.append('todoListMarkdown', newTodoListMarkdown);
805805

806-
// Pass other existing fields to satisfy schema, but they won't be "updated" by this action
807-
// if the updateTaskAction is smart enough to only update provided fields.
808-
// Assuming updateTaskAction only updates fields present in formData or changed.
809806
formData.append('title', taskToManageSubtasks.title);
810807
formData.append('status', taskToManageSubtasks.status);
811808
if (taskToManageSubtasks.description) formData.append('description', taskToManageSubtasks.description);
@@ -829,13 +826,12 @@ function ProjectDetailPageContent() {
829826
}
830827

831828
debounceTimers.current[taskUuid] = setTimeout(() => {
832-
lastSubmitSourceRef.current = null; // Not from main edit dialog or subtask dialog
829+
lastSubmitSourceRef.current = null;
833830
const formData = new FormData();
834831
formData.append('taskUuid', taskUuid);
835832
formData.append('projectUuid', project.uuid);
836833
formData.append('todoListMarkdown', newTodoListMarkdown);
837834

838-
// Pass other existing fields
839835
formData.append('title', taskToUpdate.title);
840836
formData.append('status', taskToUpdate.status);
841837
if (taskToUpdate.description) formData.append('description', taskToUpdate.description);
@@ -881,10 +877,9 @@ function ProjectDetailPageContent() {
881877
formData.append('projectUuid', project.uuid);
882878
formData.append('status', newStatus as string);
883879

884-
// Pass other fields to satisfy schema for updateTaskAction
885880
const taskToUpdate = tasks.find(t => t.uuid === taskUuid);
886881
if (taskToUpdate) {
887-
formData.append('title', taskToUpdate.title); // Required by schema if not optional
882+
formData.append('title', taskToUpdate.title);
888883
}
889884

890885

@@ -979,11 +974,10 @@ function ProjectDetailPageContent() {
979974
if (grouped[task.status]) {
980975
grouped[task.status].push(task);
981976
} else {
982-
grouped['Archived'].push(task); // Default to Archived if status is unexpected
977+
grouped['Archived'].push(task);
983978
}
984979
});
985980

986-
// Sort tasks within each status group: pinned first, then by updatedAt descending
987981
for (const status in grouped) {
988982
grouped[status as TaskStatus].sort((a, b) => {
989983
if (a.isPinned && !b.isPinned) return -1;
@@ -1003,29 +997,27 @@ function ProjectDetailPageContent() {
1003997

1004998
const handleTagsStringInputChange = (
1005999
event: React.ChangeEvent<HTMLInputElement>,
1006-
fieldApi: any, // ControllerRenderProps from react-hook-form
1007-
formApi: any // UseFormReturn
1000+
fieldApi: any,
1001+
formApi: any
10081002
) => {
10091003
const inputValue = event.currentTarget.value;
1010-
fieldApi.onChange(inputValue); // Update form state
1004+
fieldApi.onChange(inputValue);
10111005

10121006
const fragment = getCurrentTagFragment(inputValue);
1013-
setActiveTagInputName(fieldApi.name as "tagsString"); // Ensure type safety
1007+
setActiveTagInputName(fieldApi.name as "tagsString");
10141008

10151009
if (fragment) {
10161010
const lowerFragment = fragment.toLowerCase();
1017-
// Filter out tags already fully entered in the input
10181011
const currentTagsInInput = inputValue.split(',').map(t => t.trim().toLowerCase()).filter(t => t.length > 0);
10191012
const filtered = projectTags
10201013
.filter(tag =>
10211014
tag.name.toLowerCase().startsWith(lowerFragment) &&
1022-
!currentTagsInInput.slice(0, -1).includes(tag.name.toLowerCase()) // Exclude already "committed" tags
1015+
!currentTagsInInput.slice(0, -1).includes(tag.name.toLowerCase())
10231016
)
1024-
.slice(0, 5); // Limit suggestions
1017+
.slice(0, 5);
10251018
setTagSuggestions(filtered);
10261019
setShowTagSuggestions(filtered.length > 0);
10271020

1028-
// Reset active suggestion if the typed fragment changes significantly (not just adding a character)
10291021
if (fragment !== lastTypedFragmentRef.current) {
10301022
setActiveSuggestionIndex(-1);
10311023
}
@@ -1042,30 +1034,30 @@ function ProjectDetailPageContent() {
10421034

10431035
const handleTagSuggestionClick = (
10441036
suggestion: TagType,
1045-
fieldApi: any, // ControllerRenderProps
1046-
formApi: any // UseFormReturn
1037+
fieldApi: any,
1038+
formApi: any
10471039
) => {
10481040
const currentFieldValue = fieldApi.value || "";
10491041
const parts = currentFieldValue.split(',');
1050-
parts[parts.length - 1] = suggestion.name; // Replace current fragment with full tag name
1042+
parts[parts.length - 1] = suggestion.name;
10511043

10521044
let newValue = parts.join(',');
1053-
if (!newValue.endsWith(', ')) { // Add a comma and space for the next tag
1045+
if (!newValue.endsWith(', ')) {
10541046
newValue += ', ';
10551047
}
10561048

10571049
fieldApi.onChange(newValue);
10581050
setTagSuggestions([]);
10591051
setShowTagSuggestions(false);
10601052
setActiveSuggestionIndex(-1);
1061-
lastTypedFragmentRef.current = ""; // Clear last fragment
1062-
setTimeout(() => tagInputRef.current?.focus(), 0); // Refocus input
1053+
lastTypedFragmentRef.current = "";
1054+
setTimeout(() => tagInputRef.current?.focus(), 0);
10631055
};
10641056

10651057
const handleTagInputKeyDown = (
10661058
event: React.KeyboardEvent<HTMLInputElement>,
1067-
fieldApi: any, // ControllerRenderProps
1068-
formApi: any // UseFormReturn
1059+
fieldApi: any,
1060+
formApi: any
10691061
) => {
10701062
if (showTagSuggestions && tagSuggestions.length > 0) {
10711063
if (event.key === 'ArrowDown') {
@@ -1075,10 +1067,10 @@ function ProjectDetailPageContent() {
10751067
event.preventDefault();
10761068
setActiveSuggestionIndex(prev => Math.max(prev - 1, 0));
10771069
} else if ((event.key === 'Enter' || event.key === 'Tab') && activeSuggestionIndex >= 0 && activeSuggestionIndex < tagSuggestions.length) {
1078-
event.preventDefault(); // Prevent form submission or tabbing away
1079-
event.stopPropagation(); // Stop event from bubbling
1070+
event.preventDefault();
1071+
event.stopPropagation();
10801072
handleTagSuggestionClick(tagSuggestions[activeSuggestionIndex], fieldApi, formApi);
1081-
return; // Important to return to prevent further processing
1073+
return;
10821074
} else if (event.key === 'Escape') {
10831075
event.preventDefault();
10841076
event.stopPropagation();
@@ -1088,7 +1080,6 @@ function ProjectDetailPageContent() {
10881080
return;
10891081
}
10901082
} else {
1091-
// If suggestions are not shown, still allow escape to clear things if needed
10921083
if (event.key === 'Escape') {
10931084
setShowTagSuggestions(false);
10941085
setActiveSuggestionIndex(-1);
@@ -1160,7 +1151,7 @@ function ProjectDetailPageContent() {
11601151
if (!project || !user) return;
11611152
const formData = new FormData();
11621153
formData.append('projectUuid', project.uuid);
1163-
formData.append('flowUpProjectName', project.name); // Pass FlowUp project name
1154+
formData.append('flowUpProjectName', project.name);
11641155
formData.append('useDefaultRepoName', values.useDefaultRepoName.toString());
11651156
if (!values.useDefaultRepoName && values.githubRepoName) {
11661157
formData.append('githubRepoName', values.githubRepoName);
@@ -1173,9 +1164,8 @@ function ProjectDetailPageContent() {
11731164

11741165
const handleInitiateGithubOAuth = () => {
11751166
if (!project) return;
1176-
// Construct state with redirectTo and projectUuid
11771167
const statePayload = new URLSearchParams({
1178-
redirectTo: `/projects/${project.uuid}?tab=codespace`, // Ensure redirect back to codespace
1168+
redirectTo: `/projects/${project.uuid}?tab=codespace`,
11791169
projectUuid: project.uuid,
11801170
}).toString();
11811171
window.location.href = `/api/auth/github/oauth/login?state=${encodeURIComponent(statePayload)}`;
@@ -1190,11 +1180,11 @@ function ProjectDetailPageContent() {
11901180
if (authLoading || isLoadingData || isLoadingGithubAuth) {
11911181
return (
11921182
<div className="space-y-6">
1193-
<Skeleton className="h-9 w-36 mb-4" /> {/* Back button */}
1183+
<Skeleton className="h-9 w-36 mb-4" />
11941184
<Card className="shadow-lg">
11951185
<CardHeader>
1196-
<Skeleton className="h-8 w-1/2" /> {/* Project Name */}
1197-
<Skeleton className="h-5 w-3/4 mt-2" /> {/* Description */}
1186+
<Skeleton className="h-8 w-1/2" />
1187+
<Skeleton className="h-5 w-3/4 mt-2" />
11981188
<div className="mt-3 flex flex-wrap gap-2">
11991189
<Skeleton className="h-6 w-20 rounded-full" />
12001190
<Skeleton className="h-6 w-24 rounded-full" />
@@ -1209,14 +1199,13 @@ function ProjectDetailPageContent() {
12091199
</div>
12101200
</CardContent>
12111201
</Card>
1212-
<Skeleton className="h-10 w-full" /> {/* Tabs List */}
1213-
<Card><CardContent className="p-6"><Skeleton className="h-40 w-full" /></CardContent></Card> {/* Tab Content */}
1202+
<Skeleton className="h-10 w-full" />
1203+
<Card><CardContent className="p-6"><Skeleton className="h-40 w-full" /></CardContent></Card>
12141204
</div>
12151205
);
12161206
}
12171207

12181208
if (accessDenied || !project || !user) {
1219-
// This should ideally not be reached if routing logic in useEffect is correct, but good fallback.
12201209
return (
12211210
<div className="space-y-6 text-center flex flex-col items-center justify-center min-h-[calc(100vh-12rem)]">
12221211
<Button variant="outline" onClick={() => router.push('/projects')} className="mb-4 self-start">
@@ -1234,7 +1223,7 @@ function ProjectDetailPageContent() {
12341223

12351224
return (
12361225
<div className="space-y-6">
1237-
<Button variant="outline" onClick={() => router.back()} className="mb-0"> {/* Changed from router.push('/projects') to router.back() */}
1226+
<Button variant="outline" onClick={() => router.back()} className="mb-0">
12381227
<ArrowLeft className="mr-2 h-4 w-4" /> Back
12391228
</Button>
12401229

@@ -1257,14 +1246,13 @@ function ProjectDetailPageContent() {
12571246
<CardDescription className="mt-1">No description provided.</CardDescription>
12581247
)}
12591248
<div className="mt-2 flex flex-wrap gap-2">
1260-
{projectTags.slice(0, 5).map(tag => ( // Only show a few tags initially
1249+
{projectTags.slice(0, 5).map(tag => (
12611250
<Badge key={tag.uuid} style={{ backgroundColor: tag.color }} className="text-white text-xs">{tag.name}</Badge>
12621251
))}
12631252
{projectTags.length > 5 && <Badge variant="outline">+{projectTags.length - 5} more</Badge>}
12641253
</div>
12651254
</div>
12661255
<div className="flex gap-2 flex-shrink-0">
1267-
{/* Edit Project Dialog */}
12681256
<Dialog open={isEditDialogOpen} onOpenChange={setIsEditDialogOpen}>
12691257
<DialogTrigger asChild>
12701258
<Button variant="outline" size="sm" disabled={!canManageProjectSettings}>
@@ -1320,7 +1308,6 @@ function ProjectDetailPageContent() {
13201308
</Form>
13211309
</DialogContent>
13221310
</Dialog>
1323-
{/* Delete Project Alert Dialog (Placeholder) */}
13241311
<AlertDialog>
13251312
<AlertDialogTrigger asChild>
13261313
<Button variant="destructive" size="sm" disabled={currentUserRole !== 'owner'}>
@@ -1365,7 +1352,6 @@ function ProjectDetailPageContent() {
13651352
<TabsTrigger value="settings"><Settings2 className="mr-2 h-4 w-4"/>Team & Settings</TabsTrigger>
13661353
</TabsList>
13671354

1368-
{/* TASKS TAB */}
13691355
<TabsContent value="tasks" className="mt-4">
13701356
<Card>
13711357
<CardHeader className="flex flex-row justify-between items-center">
@@ -1698,7 +1684,6 @@ function ProjectDetailPageContent() {
16981684
</Dialog>
16991685
</TabsContent>
17001686

1701-
{/* README TAB */}
17021687
<TabsContent value="readme" className="mt-4">
17031688
<Card>
17041689
<CardHeader className="flex flex-row justify-between items-center">
@@ -1734,7 +1719,6 @@ function ProjectDetailPageContent() {
17341719
</Card>
17351720
</TabsContent>
17361721

1737-
{/* DOCUMENTS TAB */}
17381722
<TabsContent value="documents" className="mt-4">
17391723
<Card>
17401724
<CardHeader className="flex flex-row justify-between items-center">
@@ -1881,7 +1865,6 @@ function ProjectDetailPageContent() {
18811865
</DialogContent>
18821866
</Dialog>
18831867

1884-
{/* ANNOUNCEMENTS TAB */}
18851868
<TabsContent value="announcements" className="mt-4">
18861869
<Card>
18871870
<CardHeader className="flex flex-row justify-between items-center">
@@ -1989,7 +1972,6 @@ function ProjectDetailPageContent() {
19891972
</Card>
19901973
</TabsContent>
19911974

1992-
{/* CODESPACE TAB */}
19931975
<TabsContent value="codespace" className="mt-4">
19941976
<Card>
19951977
<CardHeader>
@@ -2044,12 +2026,12 @@ function ProjectDetailPageContent() {
20442026
control={linkGithubForm.control}
20452027
name="useDefaultRepoName"
20462028
render={({ field }) => (
2047-
<FormItem className="flex flex-row items-start space-x-3 space-y-0 rounded-md border p-4 shadow-sm bg-background/50">
2029+
<FormItem className="flex flex-row items-center space-x-3 space-y-0 rounded-md border p-4 shadow-sm bg-background/50">
20482030
<FormControl>
20492031
<Checkbox
20502032
checked={field.value}
20512033
onCheckedChange={(checked) => {
2052-
field.onChange(Boolean(checked)); // Ensure it's a boolean
2034+
field.onChange(Boolean(checked));
20532035
if (Boolean(checked)) {
20542036
linkGithubForm.setValue('githubRepoName', '');
20552037
linkGithubForm.clearErrors('githubRepoName');
@@ -2111,28 +2093,24 @@ function ProjectDetailPageContent() {
21112093
</div>
21122094
</CardHeader>
21132095
<CardContent className="space-y-4">
2114-
<p className="text-sm">
2115-
This project is linked to the GitHub repository:
2116-
</p>
2117-
<div className="flex items-center gap-2 p-3 bg-background/50 rounded-md border">
2118-
<Github className="h-5 w-5 text-foreground" />
2096+
<div className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-3">
2097+
<p className="text-sm">
2098+
This project is linked to:
21192099
<a
2120-
href={project.githubRepoUrl}
2121-
target="_blank"
2122-
rel="noopener noreferrer"
2123-
className="font-mono text-sm text-primary hover:underline break-all"
2100+
href={project.githubRepoUrl}
2101+
target="_blank"
2102+
rel="noopener noreferrer"
2103+
className="font-mono text-sm text-primary hover:underline break-all block sm:inline ml-1"
21242104
>
2125-
{project.githubRepoName || project.githubRepoUrl}
2105+
{project.githubRepoName || project.githubRepoUrl}
21262106
</a>
2127-
<Button variant="ghost" size="icon" className="h-7 w-7 ml-auto" onClick={() => copyToClipboard(project.githubRepoUrl!, 'Repository URL')}><Link2 className="h-4 w-4"/></Button>
2128-
</div>
2129-
{canManageCodeSpace && (
2130-
<Button size="lg" className="w-full mt-4 shadow-sm" asChild>
2107+
</p>
2108+
<Button size="lg" className="w-full sm:w-auto shadow-sm" asChild>
21312109
<Link href={`/projects/${projectUuid}/codespace/files`}>
21322110
<FileCode className="mr-2 h-5 w-5"/> Browse & Edit Repository Files
21332111
</Link>
21342112
</Button>
2135-
)}
2113+
</div>
21362114
<div className="grid grid-cols-1 sm:grid-cols-2 gap-3 text-sm pt-4">
21372115
<div>
21382116
<Label htmlFor="git-https-url" className="text-xs text-muted-foreground">HTTPS Clone URL</Label>
@@ -2183,7 +2161,6 @@ function ProjectDetailPageContent() {
21832161
</Card>
21842162
</TabsContent>
21852163

2186-
{/* TEAM & SETTINGS TAB */}
21872164
<TabsContent value="settings" className="mt-4">
21882165
<Card>
21892166
<CardHeader className="flex flex-row justify-between items-center">

0 commit comments

Comments
 (0)