Skip to content

Commit

Permalink
refactor: small refactors and started prep for connections overview i…
Browse files Browse the repository at this point in the history
…nformation in main workspaces page [2024-12-31]
  • Loading branch information
CHRISCARLON committed Dec 31, 2024
1 parent 75fe5fe commit e83150e
Show file tree
Hide file tree
Showing 7 changed files with 116 additions and 91 deletions.
1 change: 0 additions & 1 deletion gridwalk-ui/src/app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,6 @@ export default function Home() {

{/* Register Interest Form */}
<RegisterInterestForm />

{/* Footer */}
<footer className="py-12">
<div className="mx-auto max-w-7xl px-6 md:flex md:items-center md:justify-between">
Expand Down
7 changes: 5 additions & 2 deletions gridwalk-ui/src/app/workspace/WorkspaceContext.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
"use client";
import React, { createContext, useContext } from "react";

// Define the shape of a single workspace object and the context type
type Workspace = {
id: string;
name: string;
};

type WorkspaceContextType = {
workspaces: Workspace[];
};

// Create a context to share workspace data across components
const WorkspaceContext = createContext<WorkspaceContextType | undefined>(
undefined,
undefined
);

// Provider component that makes workspaces data available to child components
export function WorkspaceProvider({
children,
workspaces,
Expand All @@ -28,6 +30,7 @@ export function WorkspaceProvider({
);
}

// Custom hook to consume workspace data from any child component
export function useWorkspaces() {
const context = useContext(WorkspaceContext);
if (context === undefined) {
Expand Down
72 changes: 38 additions & 34 deletions gridwalk-ui/src/app/workspace/actions.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
'use server'
import { cookies } from 'next/headers'
import { redirect } from 'next/navigation'
"use server";
import { cookies } from "next/headers";
import { redirect } from "next/navigation";

// Define profile data to be returned
export type ProfileData = {
first_name: string;
last_name: string;
email: string;
}
};

// Fetch profile data
export async function getProfile(): Promise<ProfileData> {
try {
const cookieStore = await cookies();
const sessionCookie = cookieStore.get("sid");

if (!sessionCookie?.value) {
throw new Error("No session cookie found");
}
Expand Down Expand Up @@ -43,66 +45,68 @@ export async function getProfile(): Promise<ProfileData> {
}
}

// create workspace action
export async function createWorkspace(name: string) {
const cookieStore = await cookies()
const sid = cookieStore.get('sid')
const cookieStore = await cookies();
const sid = cookieStore.get("sid");

const response = await fetch(`${process.env.GRIDWALK_API}/workspace`, {
method: 'POST',
method: "POST",
headers: {
'Authorization': `Bearer ${sid?.value}`,
'Content-Type': 'application/json'
Authorization: `Bearer ${sid?.value}`,
"Content-Type": "application/json",
},
body: JSON.stringify({ name })
})
body: JSON.stringify({ name }),
});

if (!response.ok) {
throw new Error(`Failed to create workspace: ${response.statusText}`)
throw new Error(`Failed to create workspace: ${response.statusText}`);
}
}

// Define types in order to read in created / available workspaces
export type Workspace = {
id: string;
name: string;
}
};

export type Workspaces = Workspace[];

export async function getWorkspaces(): Promise<Workspaces> {
const cookieStore = await cookies()
const sid = cookieStore.get('sid')
const cookieStore = await cookies();
const sid = cookieStore.get("sid");
const response = await fetch(`${process.env.GRIDWALK_API}/workspaces`, {
headers: {
Authorization: `Bearer ${sid?.value}`
}
})
const data = await response.json()

return data
Authorization: `Bearer ${sid?.value}`,
},
});
const data = await response.json();
return data;
}

// Logout action
export async function logout() {
const cookieStore = await cookies()
const sid = cookieStore.get('sid')
const cookieStore = await cookies();
const sid = cookieStore.get("sid");

if (sid) {
try {
const response = await fetch(`${process.env.GRIDWALK_API}/logout`, {
method: 'POST',
method: "POST",
headers: {
'Authorization': `Bearer ${sid.value}`,
Authorization: `Bearer ${sid.value}`,
},
})
});
if (!response.ok) {
throw new Error('Logout failed')
throw new Error("Logout failed");
}
} catch (error) {
console.error('Logout error:', error)
console.error("Logout error:", error);
}
// Remove the sid cookie regardless of API call success
cookieStore.delete('sid')
cookieStore.delete("sid");
}

// Use redirect() after all operations are complete
redirect('/')
redirect("/");
}
9 changes: 7 additions & 2 deletions gridwalk-ui/src/app/workspace/createWorkspaceModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Button } from "@/components/ui/button";

// Sidebar for the initial workspace page - appears on righthand side of the page
// Sidebar for the initial workspace page - appears on righthand side of the main workspaces page
interface CreateWorkspaceModalProps {
isOpen: boolean;
onClose: () => void;
Expand All @@ -24,10 +24,12 @@ export function CreateWorkspaceModal({
onClose,
onCreate,
}: CreateWorkspaceModalProps) {
// Define state
const router = useRouter();
const [isCreating, setIsCreating] = useState(false);
const [workspaceName, setWorkspaceName] = useState("");

// Define what happens when creating new workspace submission
const handleSubmit = async () => {
if (!workspaceName.trim()) return;

Expand Down Expand Up @@ -82,21 +84,24 @@ export function CreateWorkspaceModal({
);
}

// Sidebar for the sidebar - appears as a "+" next to the sidebar title
// Create worksapce modal for the sidebar - appears as a "+" next to the sidebar title
interface CreateWorkspaceSidebarProps {
isOpen: boolean;
onClose: () => void;
onCreate: (name: string) => Promise<void>;
}

// THIS WORKS THE SAME WAY AS THE MODAL ABOVE
export function CreateWorkspaceSidebar({
isOpen,
onClose,
onCreate,
}: CreateWorkspaceSidebarProps) {
// Set state
const [workspaceName, setWorkspaceName] = useState("");
const [isCreating, setIsCreating] = useState(false);

// Define what happens when creating new workspace submission
const handleSubmit = async () => {
if (!workspaceName.trim()) return;
try {
Expand Down
39 changes: 21 additions & 18 deletions gridwalk-ui/src/app/workspace/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ interface WorkspaceWithDetails {
}

// Plan card value
// TODO need this to refelct the actual plans people will have
// TODO need this to refelct the actual plans that people will have in the future - will be to read from account information at some point
const currentPlan = "Private Beta";

// Create statcard
Expand Down Expand Up @@ -75,13 +75,16 @@ export default function WorkspacePage() {
const fetchWorkspaceDetails = async () => {
setLoading(true);
try {
const uniqueMemebers = new Set<string>();
const detailsPromises = workspaces.map(async (workspace) => {
try {
const [projects, members] = await Promise.all([
getProjects(workspace.id),
getWorkspaceMembers(workspace.id),
]);

members.forEach((member) => uniqueMemebers.add(member.email));

const adminCount = members.filter((m) => m.role === "Admin").length;
const readOnlyCount = members.filter(
(m) => m.role === "Read"
Expand Down Expand Up @@ -118,13 +121,9 @@ export default function WorkspacePage() {
(sum, workspace) => sum + workspace.projectCount,
0
);
const membersTotal = results.reduce(
(sum, workspace) => sum + workspace.memberCount,
0
);

setTotalProjects(projectsTotal);
setTotalMembers(membersTotal);
setTotalMembers(uniqueMemebers.size);
} catch (error) {
console.error("Failed to fetch workspace details:", error);
} finally {
Expand All @@ -142,6 +141,9 @@ export default function WorkspacePage() {
}
}, [workspaces]);

// Define Title banner, stat cards, worksapce overview section, connections overview section
// TODO add in connection info
// TODO turn this into a space to manage workspaces, data, use cases, etc
return (
<div className="w-full min-h-screen bg-gray-50">
<div className="max-w-7xl mx-auto p-6 md:p-8">
Expand All @@ -163,26 +165,19 @@ export default function WorkspacePage() {
title="Total Workspaces"
value={workspaces.length}
icon={FolderKanban}
description="Active workspaces"
/>
<StatCard
title="Total Projects"
value={totalProjects}
icon={MapIcon}
description="Across all workspaces"
/>
<StatCard
title="Active Members"
value={totalMembers}
icon={Users}
description="All workspace members"
/>
<StatCard title="Active Members" value={totalMembers} icon={Users} />
</div>

<div className="bg-white rounded-xl shadow-sm border border-gray-500 overflow-hidden">
<div className="bg-white rounded-xl shadow-sm border border-gray-500 overflow-hidden mb-8">
<div className="p-4 border-b border-gray-200">
<h2 className="text-lg font-semibold text-black">
Your Workspaces
Workspaces Overview
</h2>
</div>
<div className="p-2">
Expand All @@ -208,7 +203,7 @@ export default function WorkspacePage() {
{workspace.projectCount} projects •{" "}
{workspace.memberCount} members •{" "}
{workspace.adminCount} admins •{" "}
{workspace.readOnlyCount} viewers
{workspace.readOnlyCount} read-only
</p>
</div>
</div>
Expand All @@ -219,7 +214,7 @@ export default function WorkspacePage() {
<div className="text-center py-12">
<FolderCheck className="w-12 h-12 text-gray-400 mx-auto mb-4" />
<h3 className="text-lg font-medium text-gray-900 mb-2">
No workspaces yet
You have no workspaces yet
</h3>
<p className="text-gray-500 mb-4">
Create your first workspace to get started
Expand All @@ -232,6 +227,14 @@ export default function WorkspacePage() {
)}
</div>
</div>

<div className="bg-white rounded-xl shadow-sm border border-gray-500 overflow-hidden">
<div className="p-4 border-b border-gray-200">
<h2 className="text-lg font-semibold text-black">
Connections Overview
</h2>
</div>
</div>
</div>

<div className="fixed bottom-0 right-0 p-6">
Expand Down
2 changes: 1 addition & 1 deletion gridwalk-ui/src/app/workspace/profileModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ const ProfileModal = ({ profileData }: ProfileModalProps) => {
</div>
</div>
</div>
{/* TODO implement account settings functionality */}
{/* TODO implement account settings functionality - things like current payment plan, etc */}
<div className="flex space-x-2">
<Button className="flex-1">
<Settings className="h-4 w-4 mr-2" />
Expand Down
Loading

0 comments on commit e83150e

Please sign in to comment.