Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add new Navigation for editor #1163

Merged
merged 4 commits into from
Oct 21, 2024
Merged

Conversation

NiallJoeMaher
Copy link
Contributor

✨ Codu Pull Request 💻

Fixes #1079

Pull Request details

  • Adds new navigation for editor view to clean up the page
  • Show saved status in the navbar
  • Based on designs in the issue
  • Changed base layout to enable new navigation

Any Breaking changes

  • None

Associated Screenshots

Screen.Recording.2024-10-21.at.00.40.58.mov

@NiallJoeMaher NiallJoeMaher requested a review from a team as a code owner October 20, 2024 22:46
Copy link

vercel bot commented Oct 20, 2024

@NiallJoeMaher is attempting to deploy a commit to the Codú Team on Vercel.

A member of the Team first needs to authorize it.

Copy link
Contributor

coderabbitai bot commented Oct 20, 2024

Walkthrough

The pull request introduces multiple changes across various files, including the removal of a page component for creating posts, the restructuring of layout components, and enhancements to the editor's functionality. A new navigation component for the editor is added, along with a not-found page. The handling of post statuses has been updated, and session management has been integrated into the editor's create component. Overall, the changes streamline the user experience and improve session handling within the editor interface.

Changes

File Path Change Summary
app/(app)/create/[[...paramsArr]]/page.tsx Removed page component for creating a new post, including its metadata and session handling.
app/(app)/layout.tsx Restructured RootLayout by removing several wrapping components and simplifying the JSX structure.
app/(app)/my-posts/_client.tsx Updated post status handling by replacing PostStatus with a new status object in the MyPosts component.
app/(editor)/create/[[...paramsArr]]/_client.tsx Enhanced Create component with session management and improved error handling; updated post status logic.
app/(editor)/create/[[...paramsArr]]/navigation.tsx Added new EditorNav component for navigation in the editor, managing user sessions and notifications.
app/(editor)/create/[[...paramsArr]]/not-found.tsx Introduced notfound component for handling not-found scenarios in the editor.
app/(editor)/create/[[...paramsArr]]/page.tsx Added a new page component for editing posts, including session checks and metadata.
app/layout.tsx Enhanced layout structure with new providers and components for improved functionality.
utils/post.ts Updated post status constants and type definitions for better type safety and clarity.

Assessment against linked issues

Objective Addressed Explanation
Add sticky navigation bar for the editor (#1079)
Remove unnecessary elements from the editor nav (#1079)
Implement post status indicator in the editor nav (#1079) Status indicator implementation details are unclear.
Move "Publish" button to the sticky navigation (#1079)

Possibly related PRs

  • Update and fix Sentry and Algolia Search #1060: The changes in the main PR involve session management and rendering based on user authentication, which aligns with the updates made to the Search.tsx component in this PR that also deals with user session handling.
  • Fix/e2e tests #1061: This PR focuses on fixing end-to-end tests, which may relate to the user authentication checks in the main PR, ensuring that the tests reflect the expected behavior of the application regarding user sessions.
  • feat: Add auto-apply markdown features on editor: Enable WYSIWYG #1068: The enhancements to the editor's functionality in this PR may relate to the user experience when creating posts, similar to the main PR's focus on rendering content based on user sessions.
  • [fix] Post Sorting and Timestamp Display in Your Posts Section #1095: The updates to the MyPosts component in this PR involve rendering logic based on timestamps, which could be relevant to the session management and rendering logic in the main PR.
  • UI part done for posting jobs #1106: The job posting UI changes in this PR may relate to the overall user experience when creating content, similar to the main PR's focus on rendering based on user sessions.

Suggested labels

hacktoberfest-accepted, hacktoberfest

🐇 In the editor's den, where ideas bloom,
A nav now sticks, dispelling the gloom.
With sessions in hand and statuses bright,
We craft and we save, from morning till night.
So hop on this change, let creativity flow,
For Codú's new path is ready to grow! 🌱


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

vercel bot commented Oct 20, 2024

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
codu ✅ Ready (Inspect) Visit Preview 💬 Add feedback Oct 20, 2024 11:27pm

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 11

🧹 Outside diff range and nitpick comments (9)
app/(editor)/create/[[...paramsArr]]/not-found.tsx (1)

3-5: Rename component to follow React naming conventions.

The component's functionality is correct, but its name should be in PascalCase to follow React component naming conventions.

Apply this change:

-const notfound = () => {
+const NotFound = () => {
   return <NotFound />;
 };
utils/post.ts (1)

Line range hint 7-11: Structured export of status constants

The introduction of the status object is a good approach. It provides a structured way to access the status constants while maintaining backwards compatibility. The use of shorthand property names is clean and follows modern JavaScript practices.

For consistency with the PostStatus type, consider using as const for the entire object:

export const status = {
  SCHEDULED,
  PUBLISHED,
  DRAFT,
} as const;

This would make status a readonly object with literal type values, further enhancing type safety.

app/(editor)/create/[[...paramsArr]]/page.tsx (2)

5-28: LGTM: Comprehensive metadata with room for improvement.

The metadata object is well-structured and provides excellent SEO optimization. It includes relevant title, description, keywords, and Open Graph properties, which are crucial for discoverability and social sharing.

Consider using an environment variable for the metadataBase URL to make it more flexible across different environments:

-  metadataBase: new URL("https://www.codu.co"),
+  metadataBase: new URL(process.env.NEXT_PUBLIC_BASE_URL || "https://www.codu.co"),

Don't forget to add the NEXT_PUBLIC_BASE_URL to your environment variables.


30-37: LGTM: Well-structured server-side rendered component with proper authentication.

The Page component effectively handles server-side authentication and renders the appropriate content based on the user's session status. It follows best practices for Next.js server-side rendering and authentication flow.

Consider adding error handling to catch any potential issues with getServerAuthSession():

 export default async function Page() {
-  const session = await getServerAuthSession();
+  try {
+    const session = await getServerAuthSession();
+    if (!session) {
+      redirect("/get-started");
+    }
+    return <Content session={session} />;
+  } catch (error) {
+    console.error("Error fetching session:", error);
+    redirect("/error"); // Redirect to an error page
+  }
-  if (!session) {
-    redirect("/get-started");
-  }
-
-  return <Content session={session} />;
 }

This change will help gracefully handle any unexpected errors during the authentication process.

app/(app)/layout.tsx (1)

Provider Components Still in Use:

  • ThemeProvider is still imported and used in app/layout.tsx and app/(app)/layout.tsx.
  • TRPCReactProvider remains imported and utilized in both app/layout.tsx and app/(app)/layout.tsx.
  • AuthProvider is still present in app/layout.tsx and app/(app)/layout.tsx.
  • ProgressBar continues to be used in multiple files, including app/layout.tsx and app/(app)/layout.tsx.

These components were intended to be removed from app/(app)/layout.tsx, but they are still actively used, which may lead to inconsistencies in theming, state management, authentication, and loading indicators.

🔗 Analysis chain

Line range hint 1-15: Verify the impact of removed provider components

Several important provider components have been removed from the imports and the layout structure:

  • ThemeProvider
  • TRPCReactProvider
  • AuthProvider
  • ProgressBar

These changes could potentially affect the application's theming, state management, authentication, and loading indicators.

Please ensure that these functionalities are still available where needed throughout the application. Run the following script to check for their usage in other parts of the codebase:

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for usage of removed components in other files

echo "Checking for ThemeProvider usage:"
rg "ThemeProvider"

echo "Checking for TRPCReactProvider usage:"
rg "TRPCReactProvider"

echo "Checking for AuthProvider usage:"
rg "AuthProvider"

echo "Checking for ProgressBar usage:"
rg "ProgressBar"

Length of output: 2586


Script:

#!/bin/bash
# Description: Check for usage of removed components in other files

echo "Checking for ThemeProvider usage:"
rg "ThemeProvider"

echo "Checking for TRPCReactProvider usage:"
rg "TRPCReactProvider"

echo "Checking for AuthProvider usage:"
rg "AuthProvider"

echo "Checking for ProgressBar usage:"
rg "ProgressBar"

Length of output: 2694

app/(editor)/create/[[...paramsArr]]/navigation.tsx (1)

30-32: Handle the notification query more effectively

The useQuery hook for fetching notification count is enabled based on the session:

const { data: count } = api.notification.getCount.useQuery(undefined, {
  enabled: !!session,
});

Consider initializing count to 0 when there is no session to avoid potential undefined issues and simplify the usage:

-const { data: count } = api.notification.getCount.useQuery(undefined, {
+const { data: count = 0 } = api.notification.getCount.useQuery(undefined, {
app/(editor)/create/[[...paramsArr]]/_client.tsx (3)

Line range hint 358-364: Optimize auto-save logic in useEffect

The auto-save useEffect depends on several conditions. To improve readability and prevent unnecessary saves, consider restructuring the conditions:

  • Combine related conditions using logical operators.
  • Add comments to explain the purpose of each condition.
  • Ensure that savePost() is only called when necessary.

389-392: Add missing dependency to 'handlePublish' function

If handlePublish depends on any state or props (e.g., isDisabled), ensure that these are included in its dependency array if handlePublish is wrapped with useCallback. This prevents stale values from being used when the function is invoked.


776-778: Remove unnecessary comments

The comments {/* Remove the save status messages */} and {/* Next button already removed */} might be outdated or unnecessary. Consider removing them to keep the codebase clean and maintainable.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 77aa243 and 2304cf2.

📒 Files selected for processing (9)
  • app/(app)/create/[[...paramsArr]]/page.tsx (0 hunks)
  • app/(app)/layout.tsx (1 hunks)
  • app/(app)/my-posts/_client.tsx (4 hunks)
  • app/(editor)/create/[[...paramsArr]]/_client.tsx (10 hunks)
  • app/(editor)/create/[[...paramsArr]]/navigation.tsx (1 hunks)
  • app/(editor)/create/[[...paramsArr]]/not-found.tsx (1 hunks)
  • app/(editor)/create/[[...paramsArr]]/page.tsx (1 hunks)
  • app/layout.tsx (2 hunks)
  • utils/post.ts (1 hunks)
💤 Files with no reviewable changes (1)
  • app/(app)/create/[[...paramsArr]]/page.tsx
🧰 Additional context used
🔇 Additional comments (22)
app/(editor)/create/[[...paramsArr]]/not-found.tsx (3)

1-1: LGTM: Import statement is correct and follows good practices.

The import statement correctly uses the @ alias for importing from the project root, and the component name matches the file name.


7-7: LGTM: Default export is correct.

The default export statement is correct. If you rename the component as suggested earlier, remember to update this line as well:

-export default notfound;
+export default NotFound;

1-7: Implementation aligns well with PR objectives.

This new not-found.tsx file successfully implements a dedicated UI for scenarios where content is not found in the editor create route. It aligns with the PR objectives of enhancing the editor view and improving navigation. The implementation is simple and effective, leveraging an existing NotFound component.

Consider the following suggestions to further improve the code:

  1. Rename the component to NotFound (PascalCase) to follow React naming conventions.
  2. Update the default export statement if you rename the component.

These minor adjustments will enhance code consistency and maintainability.

utils/post.ts (3)

1-3: Improved type safety with as const assertions

The use of as const for the status constants is a good practice. It creates readonly literal types, which enhances type inference and safety when these constants are used throughout the codebase. This change maintains the existing behavior while providing better type checking.


5-5: Enhanced type definition for PostStatus

The new PostStatus type definition as a union of constant types is an improvement. It ensures that PostStatus always accurately reflects the available status constants, reducing the risk of inconsistencies. This approach is more type-safe and flexible than the previous enum-like object.


Line range hint 1-38: Overall improvement in post status management

The changes in this file significantly enhance the type safety and organization of post status-related code. By using as const assertions, introducing a union type for PostStatus, and providing a structured status object, the code becomes more robust and less prone to errors.

These modifications align well with the PR objectives of improving the editor's functionality and streamlining the user experience. They provide a solid foundation for consistent handling of post statuses across the application.

The utility functions getPostStatus and isValidScheduleTime remain unchanged, preserving existing behavior while benefiting from the improved type definitions.

app/(editor)/create/[[...paramsArr]]/page.tsx (2)

1-3: LGTM: Imports are appropriate and follow best practices.

The imports are concise and relevant to the file's functionality. They include necessary Next.js utilities, a local component, and an authentication helper.


1-37: Overall, excellent implementation of the editor page.

This new file successfully implements the server-side rendered page for editing posts, aligning well with the PR objectives. It includes proper authentication checks, comprehensive metadata for SEO optimization, and a clean component structure. The changes contribute to the new navigation system for the editor and address the requirements outlined in the linked issue #1079.

A few minor suggestions were made to improve environment flexibility and error handling, but these are not critical issues. Great job on this implementation!

app/(app)/layout.tsx (2)

82-88: Simplified layout structure

The layout structure has been significantly simplified:

  • Removed wrapping components like ThemeProvider, AuthProvider, and TRPCReactProvider.
  • Directly rendering Nav, children, and Footer.

While this simplification can improve readability, it's crucial to ensure that the removed context providers don't negatively impact the functionality of child components.

Please verify that all child components still have access to necessary context and state management. You may need to update components that relied on these providers.


82-86: Consistency with PR objectives

The changes to the Nav component align with the PR objectives:

  • The navigation bar is still present, which is consistent with the goal of implementing a sticky navigation bar.
  • The session prop is passed, which could be used for displaying user-specific information.
  • The algoliaSearchConfig is provided, which might be used for search functionality in the navigation.
  • The username is passed, which aligns with the objective of including a user icon in the navigation.

However, there are some aspects of the PR objectives that are not directly visible in this file:

  • The "Publish" button relocation
  • The save status indicator
  • Dark mode toggle

Please ensure that these features are implemented in the Nav component or other relevant parts of the application. Run the following script to check for their implementation:

#!/bin/bash
# Description: Check for implementation of required features

echo "Checking for Publish button implementation:"
rg -i "publish.*button"

echo "Checking for save status indicator:"
rg -i "save.*status|status.*indicator"

echo "Checking for dark mode toggle:"
rg -i "dark.*mode.*toggle|theme.*toggle"
app/(app)/my-posts/_client.tsx (5)

136-138: LGTM! Correct usage of the new status object.

The post status determination logic has been correctly updated to use the new status.DRAFT instead of PostStatus.DRAFT. This change is consistent with the import statement modification and maintains the existing logic.


161-161: LGTM! Correct usage of the new status object for scheduled posts.

The condition for checking scheduled post status has been properly updated to use status.SCHEDULED. This change is consistent with the new status object structure and maintains the existing logic.


165-165: LGTM! Consistent usage of the new status object for published and draft posts.

The conditions for checking published and draft post statuses have been correctly updated to use status.PUBLISHED and status.DRAFT respectively. These changes are consistent with the new status object structure and maintain the existing logic.

Also applies to: 177-177


Line range hint 1-248: Summary: Successful migration to new status object structure

The changes in this file successfully migrate the usage of PostStatus enum to the new status object structure. All references to post statuses have been updated consistently, maintaining the existing logic while improving type safety and clarity. These changes align with the PR objectives and the restructuring mentioned in the AI-generated summary.

Key points:

  1. Import statement updated to use status and getPostStatus.
  2. All post status checks (draft, scheduled, published) now use the new status object.
  3. The overall functionality of the MyPosts component remains unchanged.

These updates contribute to a more maintainable and type-safe codebase.


21-21: LGTM! Verify consistency across the codebase.

The import statement has been updated to use the new status object and getPostStatus function. This change aligns with the restructuring of PostStatus mentioned in the AI summary.

To ensure consistency, let's verify that this change has been applied across the codebase:

app/layout.tsx (3)

1-1: Import Statement Added Correctly

The import of headers from "next/headers" is appropriate for accessing request headers in a server component.


9-13: New Providers Imported Successfully

The imports for ThemeProvider, TRPCReactProvider, AuthProvider, ProgressBar, and PromptProvider have been added correctly and reference the appropriate modules.


71-80: Providers Integrated Properly into Layout

The nesting of the new providers within the A11yProvider enhances the modularity and state management of the application. Wrapping children with AuthProvider, ThemeProvider, TRPCReactProvider, and PromptProvider ensures that these contexts are available throughout the app.

app/(editor)/create/[[...paramsArr]]/navigation.tsx (1)

60-157: ⚠️ Potential issue

Add the dark mode toggle to the navigation bar

According to the PR objectives, the navigation bar should include a dark mode toggle. The current implementation does not include this feature. Please add the dark mode toggle to align with the design specifications.

app/(editor)/create/[[...paramsArr]]/_client.tsx (3)

247-249: Ensure correct computation of 'currentPostStatus'

The calculation of currentPostStatus depends on data.published. Verify that data.published is always a valid date when the post is not a draft. Additionally, consider handling cases where data.published might be undefined or invalid to prevent runtime errors.


396-403: Verify props passed to 'EditorNav' component

Ensure that all props passed to EditorNav are correct and necessary:

  • session: Confirm that EditorNav requires the session object.
  • username: Double-check that session?.user?.name is the correct property for the username.
  • postStatus, unsavedChanges, onPublish, isDisabled: Verify that these props are used appropriately within EditorNav.

Line range hint 577-583: Handle 'Save draft' button rendering logic

The Save draft button is conditionally rendered when currentPostStatus === status.DRAFT. Ensure that currentPostStatus accurately reflects the post's status to prevent the button from appearing or disappearing unexpectedly.

import { Menu, Transition } from "@headlessui/react";
import { BellIcon } from "@heroicons/react/20/solid";
import { signOut } from "next-auth/react";
import { PromptLink as Link } from "@/components/PromptService/PromptLink";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Confirm the correct Link component and to prop usage

The code imports PromptLink as Link:

import { PromptLink as Link } from "@/components/PromptService/PromptLink";

Please verify that PromptLink is the intended component for navigation links and that it supports the to prop used throughout the file. If you intended to use Next.js's Link component, consider importing it from next/link and using the href prop instead.

Comment on lines 64 to 66
<Link to="/" className="flex items-center">
<Logo className="h-6 w-auto" />
</Link>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Update Link component to use the href prop

In the logo link, the Link component uses the to prop:

<Link to="/" className="flex items-center">
  <Logo className="h-6 w-auto" />
</Link>

If using Next.js's Link component, it should use the href prop. Modify the code as follows:

-<Link to="/" className="flex items-center">
+<Link href="/" className="flex items-center">

Comment on lines 86 to 88
<Link
to="/notifications"
className="focus-style relative rounded-full p-1 text-neutral-500 hover:bg-neutral-100 hover:text-neutral-600 dark:text-neutral-400 dark:hover:bg-neutral-800 dark:hover:text-white"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Ensure Link component uses the correct prop for navigation

Here, the Link component is used with the to prop:

<Link
  to="/notifications"
  className="focus-style relative rounded-full p-1 text-neutral-500 hover:bg-neutral-100 hover:text-neutral-600 dark:text-neutral-400 dark:hover:bg-neutral-800 dark:hover:text-white"
>

If Link should use the href prop, update it accordingly:

-<Link
-  to="/notifications"
+<Link
+  href="/notifications"

Comment on lines 137 to 144
to={item.href}
className={`${
active ? "bg-neutral-100" : ""
} block px-4 py-2 text-sm text-neutral-700`}
>
{item.name}
</Link>
)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Modify Link component to use href instead of to

Within the user menu, the Link component uses to={item.href}:

<Link
  to={item.href}
  className={`${
    active ? "bg-neutral-100" : ""
  } block px-4 py-2 text-sm text-neutral-700`}
>
  {item.name}
</Link>

Ensure the Link component uses the href prop:

-<Link
-  to={item.href}
+<Link
+  href={item.href}

Comment on lines +42 to +55
const getStatusText = () => {
if (postStatus === null) return null;

switch (postStatus) {
case status.DRAFT:
return unsavedChanges ? "Draft - Unsaved changes" : "Draft - Saved";
case status.PUBLISHED:
return unsavedChanges ? "Published - Unsaved changes" : "Published";
case status.SCHEDULED:
return unsavedChanges ? "Scheduled - Unsaved changes" : "Scheduled";
default:
return null;
}
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Simplify the getStatusText function

You can streamline the getStatusText function by reducing repetition:

 const getStatusText = () => {
-  if (postStatus === null) return null;
+  if (!postStatus) return null;

   const statusMap = {
     [status.DRAFT]: "Draft",
     [status.PUBLISHED]: "Published",
     [status.SCHEDULED]: "Scheduled",
   };

-  switch (postStatus) {
-    case status.DRAFT:
-      return unsavedChanges ? "Draft - Unsaved changes" : "Draft - Saved";
-    case status.PUBLISHED:
-      return unsavedChanges ? "Published - Unsaved changes" : "Published";
-    case status.SCHEDULED:
-      return unsavedChanges ? "Scheduled - Unsaved changes" : "Scheduled";
-    default:
-      return null;
-  }
+  const baseText = statusMap[postStatus];
+  if (!baseText) return null;
+  return unsavedChanges ? `${baseText} - Unsaved changes` : baseText;
 };
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const getStatusText = () => {
if (postStatus === null) return null;
switch (postStatus) {
case status.DRAFT:
return unsavedChanges ? "Draft - Unsaved changes" : "Draft - Saved";
case status.PUBLISHED:
return unsavedChanges ? "Published - Unsaved changes" : "Published";
case status.SCHEDULED:
return unsavedChanges ? "Scheduled - Unsaved changes" : "Scheduled";
default:
return null;
}
};
const getStatusText = () => {
if (!postStatus) return null;
const statusMap = {
[status.DRAFT]: "Draft",
[status.PUBLISHED]: "Published",
[status.SCHEDULED]: "Scheduled",
};
const baseText = statusMap[postStatus];
if (!baseText) return null;
return unsavedChanges ? `${baseText} - Unsaved changes` : baseText;
};


const Create = () => {
const Create = ({ session }: { session: Session | null }) => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Pass 'session' prop to 'EditorNav' component

The session prop is now passed to the Create component and then forwarded to the EditorNav component. Ensure that this prop is necessary and used appropriately within EditorNav. If EditorNav can access the session internally (e.g., via a context or a hook), consider removing the prop to simplify the component interface.

@@ -52,6 +59,7 @@
const [uploadStatus, setUploadStatus] = useState<
"loading" | "error" | "success" | "default"
>("default");
const [postStatus, setPostStatus] = useState<PostStatus | null>(null);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Initialize 'postStatus' with consistent default value

The postStatus state is initialized with null. Since postStatus is used to determine the UI state, consider initializing it with a default status, such as status.DRAFT, to avoid potential null checks elsewhere in the code.

Comment on lines +345 to +347
setPostStatus(
published ? getPostStatus(new Date(published)) : status.DRAFT,
);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Set 'postStatus' consistently after data fetch

After fetching the post data, postStatus is updated based on published. Ensure that this logic aligns with how postStatus is used elsewhere, and that it doesn't conflict with currentPostStatus. Consolidating these statuses might improve code clarity.

Comment on lines +351 to +356
if ((title + body).length < 5) {
setPostStatus(null);
} else if (postStatus === null) {
setPostStatus(status.DRAFT);
}
}, [title, body]);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Avoid setting 'postStatus' to null based on content length

Setting postStatus to null when the combined length of title and body is less than 5 might lead to unintended UI states. Instead, consider using a separate state or validation function to handle content length requirements without altering the post status.

Comment on lines +606 to +616
{currentPostStatus === status.PUBLISHED
? "Save changes"
: currentPostStatus === status.DRAFT
? isPostScheduled
? "Schedule"
: "Publish now"
: currentPostStatus === status.SCHEDULED
? isPostScheduled
? "Update schedule"
: "Publish now"
: "Publish"}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Simplify nested ternary operators for button label

The nested ternary operators used to determine the button label make the code difficult to read and maintain. Consider extracting this logic into a separate function or variable to improve readability.

Apply this refactor:

-                                {currentPostStatus === status.PUBLISHED
-                                  ? "Save changes"
-                                  : currentPostStatus === status.DRAFT
-                                    ? isPostScheduled
-                                      ? "Schedule"
-                                      : "Publish now"
-                                    : currentPostStatus === status.SCHEDULED
-                                      ? isPostScheduled
-                                        ? "Update schedule"
-                                        : "Publish now"
-                                      : "Publish"}
+                                {getButtonLabel(currentPostStatus, isPostScheduled)}

Define the getButtonLabel function:

const getButtonLabel = (postStatus, isPostScheduled) => {
  if (postStatus === status.PUBLISHED) {
    return "Save changes";
  } else if (postStatus === status.DRAFT) {
    return isPostScheduled ? "Schedule" : "Publish now";
  } else if (postStatus === status.SCHEDULED) {
    return isPostScheduled ? "Update schedule" : "Publish now";
  } else {
    return "Publish";
  }
};

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Outside diff range and nitpick comments (1)
e2e/articles.spec.ts (1)

184-185: LGTM! Consider adding a check for the new navigation bar.

The changes correctly update the test to use the new "Publish" button, which aligns with the PR objectives of relocating the "Publish" button to the navigation bar. This update accurately reflects the new user interface and workflow for publishing an article.

To further improve the test coverage and align with the PR objectives, consider adding a check for the visibility of the new navigation bar before interacting with the "Publish" button. This could help ensure that the new layout is correctly implemented. For example:

await expect(page.getByTestId('editor-navigation-bar')).toBeVisible();
await expect(page.getByRole("button", { name: "Publish" })).toBeVisible();
await page.getByRole("button", { name: "Publish" }).click();

Replace 'editor-navigation-bar' with the actual test ID or selector for the new navigation bar.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 2304cf2 and cdc2c69.

📒 Files selected for processing (3)
  • app/(editor)/create/[[...paramsArr]]/_client.tsx (9 hunks)
  • app/(editor)/create/[[...paramsArr]]/navigation.tsx (1 hunks)
  • e2e/articles.spec.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • app/(editor)/create/[[...paramsArr]]/navigation.tsx
🧰 Additional context used
🔇 Additional comments (4)
app/(editor)/create/[[...paramsArr]]/_client.tsx (4)

25-25: LGTM: Import statements and type definitions updated appropriately.

The new imports and type definitions align well with the changes in the component's functionality, including improved navigation, post status management, and session handling.

Also applies to: 29-34, 38-39


41-41: LGTM: Component signature and state updated for session and post status.

The addition of the session prop and postStatus state variable aligns with the new session handling and post status management functionality.

Also applies to: 62-62


396-403: LGTM: EditorNav component integrated effectively.

The addition of the EditorNav component with appropriate props improves the code structure by separating the navigation logic.


Line range hint 1-858: Overall improvements with some suggestions for further refinement.

The changes in this file align well with the PR objectives, improving the editor's navigation, post status management, and overall structure. The addition of the EditorNav component and enhanced post status handling are particularly noteworthy improvements.

However, there are a few areas that could be further refined:

  1. Consider improving error handling for draft fetch failures.
  2. Reconsider the approach of setting postStatus to null based on content length.
  3. Simplify complex conditional logic, such as the nested ternary operators for the publish button label.

Addressing these points would further enhance the code's readability and maintainability.

Comment on lines +198 to +200
notFound();
}
}, [draftFetchError, isError, isSuccess]);
}, [draftFetchError, isError]);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Consider alternative error handling for draft fetch failures.

While using notFound() for draft fetch errors improves the UX by avoiding error toasts, it might confuse users who expect to edit their draft. Consider displaying an error message or redirecting to a dedicated error page that explains the issue more clearly.

Comment on lines +247 to +249
const currentPostStatus = data?.published
? getPostStatus(new Date(data.published))
: PostStatus.DRAFT;
: status.DRAFT;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Reconsider setting postStatus to null based on content length.

While the changes improve post status management, setting postStatus to null when the combined length of title and body is less than 5 might lead to unintended UI states. Instead, consider using a separate state or validation function to handle content length requirements without altering the post status.

Also applies to: 345-356

Comment on lines +389 to +392
const handlePublish = () => {
if (isDisabled) return;
setOpen(true);
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Simplify nested ternary operators for button label.

The nested ternary operators used to determine the button label make the code difficult to read and maintain. Consider extracting this logic into a separate function or variable to improve readability.

Apply this refactor:

-                            {currentPostStatus === status.PUBLISHED
-                              ? "Save changes"
-                              : currentPostStatus === status.DRAFT
-                                ? isPostScheduled
-                                  ? "Schedule"
-                                  : "Publish now"
-                                : currentPostStatus === status.SCHEDULED
-                                  ? isPostScheduled
-                                    ? "Update schedule"
-                                    : "Publish now"
-                                  : "Publish"}
+                            {getButtonLabel(currentPostStatus, isPostScheduled)}

Define the getButtonLabel function:

const getButtonLabel = (postStatus, isPostScheduled) => {
  if (postStatus === status.PUBLISHED) {
    return "Save changes";
  } else if (postStatus === status.DRAFT) {
    return isPostScheduled ? "Schedule" : "Publish now";
  } else if (postStatus === status.SCHEDULED) {
    return isPostScheduled ? "Update schedule" : "Publish now";
  } else {
    return "Publish";
  }
};

Also applies to: 577-616

@John-Paul-Larkin
Copy link
Member

I see you dont have much confidence the alpha editor will be ready any time soon 🤣

@NiallJoeMaher
Copy link
Contributor Author

I see you dont have much confidence the alpha editor will be ready any time soon 🤣

Aha I do! I was going to migrate it to the main editor with a feature flag or the ability so folks can start using it. It needs to come out of alpha into here anyway.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add New Nested Layout for Editor Page
2 participants