Skip to content

feat: new feed edit#198

Merged
elliotBraem merged 12 commits intostagingfrom
feat/new-feed-edit
Jun 27, 2025
Merged

feat: new feed edit#198
elliotBraem merged 12 commits intostagingfrom
feat/new-feed-edit

Conversation

@itexpert120
Copy link
Collaborator

@itexpert120 itexpert120 commented Jun 24, 2025

Updated the feed editor to be more user friendly

Screencast.From.2025-06-24.17-31-27.mp4

Summary by CodeRabbit

  • New Features

    • Introduced a comprehensive feed editing interface, including modular components for editing feed details, configuration, image, and moderation settings.
    • Added support for toggling between form-based and JSON editing modes for feed configuration.
    • Enabled advanced configuration for sources, streaming outputs, recaps, and moderation within the feed editor.
    • Provided image upload functionality with instant feedback and JSON config synchronization.
    • Added robust loading, error, and not-found states for the feed editor.
  • Improvements

    • Refactored the feed editing page for improved modularity and maintainability.
    • Enhanced textarea styling for a better editing experience.
  • Chores

    • Added a new frontend development script for streamlined local development.
    • Updated formatting ignore rules for generated files.

@vercel
Copy link

vercel bot commented Jun 24, 2025

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

Name Status Preview Comments Updated (UTC)
curatedotfun-app ✅ Ready (Inspect) Visit Preview 💬 Add feedback Jun 27, 2025 9:58pm

@coderabbitai
Copy link

coderabbitai bot commented Jun 24, 2025

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Walkthrough

A comprehensive feed editing system was introduced, including modular React components for editing feed configurations, images, and metadata, along with robust form handling using react-hook-form and Zod validation. Supporting hooks, utility modules, and UI primitives were added or updated. The main feed editing route was refactored to utilize these new abstractions, and minor tooling and formatting updates were made.

Changes

File(s) Change Summary
apps/app/src/components/feed/EditFeedActions.tsx Added a component for save/delete feed actions with loading states.
apps/app/src/components/feed/EditFeedConfigSection.tsx Added a dual-mode (form/JSON) feed config editing component.
apps/app/src/components/feed/EditFeedForm.tsx Added a comprehensive, reactive feed config editing form with dynamic arrays and validation.
apps/app/src/components/feed/EditFeedHeader.tsx Added a header component showing feed name and subtitle.
apps/app/src/components/feed/EditFeedImageSection.tsx Added a feed image upload section with callback and toast notification.
apps/app/src/components/feed/EditFeedLoadingState.tsx Added a loading/error/not-found state display component.
apps/app/src/components/feed/form/BasicFieldsSection.tsx Added memoized component for editing basic feed fields.
apps/app/src/components/feed/form/IngestionSection.tsx Added memoized component for scheduled ingestion settings.
apps/app/src/components/feed/form/ModerationSection.tsx Added memoized component for Twitter moderation settings.
apps/app/src/components/feed/form/RecapsSection.tsx Added memoized component for managing recap configurations.
apps/app/src/components/feed/form/SourcesSection.tsx Added memoized component for managing sources and nested search queries.
apps/app/src/components/feed/form/StreamSettingsSection.tsx Added component for streaming output, transforms, and distributors with JSON config editing.
apps/app/src/components/feed/form/index.ts Added barrel file re-exporting form section components and types.
apps/app/src/components/feed/form/types.ts Added Zod schema and type for feed config form validation.
apps/app/src/hooks/use-edit-feed.ts Added a custom hook to encapsulate feed edit state, handlers, and mutations.
apps/app/src/routes/_layout/edit/feed.$feedId.tsx Refactored to use new hook and modular components for feed editing UI and logic.
apps/app/src/routeTree.gen.ts Reformatted: switched to single quotes, removed trailing semicolons/commas; no logic changes.
apps/app/src/components/ui/textarea.tsx Updated textarea styling: increased min-height, padding, border, and background adjustments.
package.json Added dev:frontend script to run frontend dev mode for the app package.
.prettierignore Added routeTree.gen.ts to Prettier ignore list.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant EditFeedComponent
    participant useEditFeed
    participant EditFeedForm
    participant EditFeedConfigSection
    participant EditFeedActions

    User->>EditFeedComponent: Navigates to feed edit page
    EditFeedComponent->>useEditFeed: Initialize with feedId
    useEditFeed->>useEditFeed: Fetch feed data, set config state
    useEditFeed-->>EditFeedComponent: Return feed data, handlers, mutations

    EditFeedComponent->>EditFeedHeader: Render with feed info
    EditFeedComponent->>EditFeedImageSection: Render with config, image handler
    EditFeedComponent->>EditFeedConfigSection: Render with config, JSON, change handlers
    EditFeedComponent->>EditFeedActions: Render with save/delete handlers and mutation state

    User->>EditFeedImageSection: Uploads new image
    EditFeedImageSection->>useEditFeed: handleImageUploaded(ipfsHash, ipfsUrl)

    User->>EditFeedConfigSection: Edits config (form or JSON)
    EditFeedConfigSection->>EditFeedForm: Edit fields (form mode)
    EditFeedForm-->>useEditFeed: onConfigChange(updatedConfig)
    EditFeedConfigSection-->>useEditFeed: onJsonChange(newJsonString)

    User->>EditFeedActions: Clicks "Save Changes"
    EditFeedActions->>useEditFeed: handleSaveChanges()
    useEditFeed->>useEditFeed: Run updateFeedMutation

    User->>EditFeedActions: Clicks "Delete Feed"
    EditFeedActions->>useEditFeed: handleDeleteFeed()
    useEditFeed->>useEditFeed: Run deleteFeedMutation, navigate away
Loading

Poem

A carrot for each shiny new form,
With fields and toggles, warm and norm.
Now feeds can morph with every click,
JSON or form—just take your pick!
Upload a bunny’s photo, too—
Save or delete, the choice is you!
🥕✨


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ 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.
    • Explain this complex logic.
    • 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 explain this code block.
    • @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 explain its main purpose.
    • @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.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

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 generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this 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

@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: 10

♻️ Duplicate comments (1)
apps/app/src/components/feed/form/SourcesSection.tsx (1)

43-43: Use consistent ID generation approach.

Same as RecapsSection, consider using a more robust ID generation method to avoid potential duplicates.

🧹 Nitpick comments (13)
apps/app/src/components/feed/EditFeedActions.tsx (2)

5-15: Remove unused prop from interface.

The currentConfig prop is defined in the interface but never used in the component implementation.

interface EditFeedActionsProps {
-  currentConfig: FeedConfig | null;
  onSaveChanges: () => Promise<void>;
  onDeleteFeed: () => Promise<void>;
  updateFeedMutation: {
    isPending: boolean;
  };
  deleteFeedMutation: {
    isPending: boolean;
  };
}

17-22: Update component parameters to match interface change.

Remove the unused currentConfig parameter from the component.

export function EditFeedActions({
-  currentConfig,
  onSaveChanges,
  onDeleteFeed,
  updateFeedMutation,
  deleteFeedMutation,
}: EditFeedActionsProps) {
apps/app/src/components/feed/EditFeedImageSection.tsx (1)

5-9: Remove unused feedId prop.

The feedId prop is defined in the interface but never used in the component implementation.

 interface EditFeedImageSectionProps {
   currentConfig: FeedConfig | null;
-  feedId: string;
   onImageUploaded: (ipfsHash: string, ipfsUrl: string) => void;
 }

And update the component signature:

 export function EditFeedImageSection({
   currentConfig,
   onImageUploaded,
 }: EditFeedImageSectionProps) {
apps/app/src/components/feed/EditFeedLoadingState.tsx (2)

16-25: Consider the impact of fixed positioning overlay.

The fixed positioning with z-50 creates a full-screen overlay that might interfere with navigation or other UI interactions. Consider whether this blocking behavior is intended, or if a more localized loading state would be better.

If non-blocking loading is preferred:

- <div className="fixed inset-0 flex items-center justify-center z-50">
+ <div className="flex items-center justify-center p-8">

5-9: Consider more specific typing for feedData.

The feedData prop is typed as unknown which provides limited type safety. Consider using a more specific type if the structure is known.

apps/app/src/components/feed/form/ModerationSection.tsx (1)

17-59: Consider extracting common logic to reduce duplication.

Both TwitterApproversField and TwitterBlacklistField share nearly identical logic for handling comma-separated values. Consider creating a reusable component or custom hook.

Example approach with a custom hook:

function useCommaSeparatedField(name: string, control: Control<FormValues>) {
  const { field, fieldState: { error } } = useController({ name, control });
  const [localValue, setLocalValue] = useState(
    field.value?.twitter?.join(", ") || ""
  );

  useEffect(() => {
    const formValue = field.value?.twitter?.join(", ") || "";
    setLocalValue(formValue);
  }, [field.value]);

  const handleBlur = () => {
    const values = { ...field.value };
    values.twitter = localValue
      .split(",")
      .map((s) => s.trim())
      .filter(Boolean);
    field.onChange(values);
  };

  return { localValue, setLocalValue, handleBlur, error };
}
apps/app/src/components/feed/form/RecapsSection.tsx (1)

39-39: Consider using a more robust ID generation method.

Using Date.now() for ID generation could theoretically create duplicates if multiple items are added in rapid succession. Consider using a UUID library or a counter-based approach.

-              id: `recap-${Date.now()}`,
+              id: `recap-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
apps/app/src/routes/_layout/edit/feed.$feedId.tsx (1)

32-40: Simplify loading state handling.

The current pattern of creating a component and checking its truthiness is unconventional. Consider a more straightforward approach.

-  // Show loading, error, or not found states
-  const loadingState = EditFeedLoadingState({
-    isLoadingFeed,
-    feedError,
-    feedData,
-  });
-
-  if (loadingState) {
-    return loadingState;
-  }
+  if (isLoadingFeed || feedError || !feedData) {
+    return (
+      <EditFeedLoadingState
+        isLoadingFeed={isLoadingFeed}
+        feedError={feedError}
+        feedData={feedData}
+      />
+    );
+  }
apps/app/src/components/feed/EditFeedConfigSection.tsx (1)

33-36: Replace setTimeout with useEffect for form synchronization.

Using setTimeout to defer form updates is a workaround. Consider using useEffect for a more React-idiomatic approach.

+  useEffect(() => {
+    if (!isJsonMode && formRef.current) {
+      formRef.current.updateFromConfig();
+    }
+  }, [isJsonMode]);
+
   const handleSwitchToFormMode = () => {
     setIsJsonMode(false);
-    // Trigger form update after switching to form mode
-    setTimeout(() => {
-      formRef.current?.updateFromConfig();
-    }, 0);
   };
apps/app/src/hooks/use-edit-feed.ts (3)

59-59: Remove or utilize the unused _ipfsHash parameter.

The _ipfsHash parameter is prefixed with underscore indicating it's unused, but it's still being passed to the function. Either remove it or implement its usage.

-  const handleImageUploaded = (_ipfsHash: string, ipfsUrl: string) => {
+  const handleImageUploaded = (ipfsHash: string, ipfsUrl: string) => {
     setCurrentConfig((prevConfig) => {
       const newConfig = {
         ...(prevConfig || { id: feedId, name: "", description: "" }),
         image: ipfsUrl,
+        // Consider storing ipfsHash if needed for future reference
       } as FeedConfig;

36-56: Extract default config values to improve maintainability.

The config initialization contains many hardcoded defaults. Consider extracting these to a separate constant or function.

+const getDefaultFeedConfig = (partial: Partial<FeedConfig>): FeedConfig => ({
+  id: partial.id || "",
+  name: partial.name || "",
+  description: partial.description || "",
+  image: partial.image || undefined,
+  enabled: partial.enabled || false,
+  moderation: partial.moderation || { approvers: { twitter: [] } },
+  outputs: partial.outputs || { stream: { enabled: false } },
+  pollingIntervalMs: partial.pollingIntervalMs || undefined,
+  sources: partial.sources || [],
+  ingestion: partial.ingestion || undefined,
+});

   useEffect(() => {
     if (feedData?.config) {
-      const configWithPotentiallyMissingFields: FeedConfig = {
-        // Ensure all fields from the schema are present, providing defaults if necessary
-        // This is important because feedData.config might be from the simpler API type
-        id: feedData.config.id,
-        name: feedData.config.name,
-        description: feedData.config.description,
-        image: feedData.config.image || undefined,
-        enabled: feedData.config.enabled || false,
-        moderation: feedData.config.moderation || {
-          approvers: { twitter: [] },
-        }, // Default
-        outputs: feedData.config.outputs || { stream: { enabled: false } },
-        pollingIntervalMs: feedData.config.pollingIntervalMs || undefined,
-        sources: feedData.config.sources || [],
-        ingestion: feedData.config.ingestion || undefined,
-      };
+      const configWithPotentiallyMissingFields = getDefaultFeedConfig(feedData.config);

113-115: Replace window.confirm with a modern confirmation dialog.

Using window.confirm is inconsistent with the modern UI approach used throughout the application. Consider implementing a proper confirmation dialog component.

Would you like me to implement a confirmation dialog component that matches your UI design system?

apps/app/src/components/feed/EditFeedForm.tsx (1)

134-134: Consider optimizing form watching for better performance.

Watching all form values triggers the debounced update logic on every change, which could impact performance with complex forms.

Consider watching only specific fields that trigger config updates, or use form state subscriptions for more granular control:

-const watchedValues = form.watch();
+// Watch only fields that affect config updates
+const watchedValues = form.watch([
+  'name', 'description', 'enabled', 'pollingIntervalMs',
+  'ingestionEnabled', 'ingestionSchedule', 'sources',
+  'streamEnabled', 'streamTransforms', 'streamDistributors',
+  'recaps', 'moderationApprovers', 'moderationBlacklist'
+]);
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7667141 and 61c4f31.

📒 Files selected for processing (18)
  • apps/app/src/components/feed/EditFeedActions.tsx (1 hunks)
  • apps/app/src/components/feed/EditFeedConfigSection.tsx (1 hunks)
  • apps/app/src/components/feed/EditFeedForm.tsx (1 hunks)
  • apps/app/src/components/feed/EditFeedHeader.tsx (1 hunks)
  • apps/app/src/components/feed/EditFeedImageSection.tsx (1 hunks)
  • apps/app/src/components/feed/EditFeedLoadingState.tsx (1 hunks)
  • apps/app/src/components/feed/form/BasicFieldsSection.tsx (1 hunks)
  • apps/app/src/components/feed/form/IngestionSection.tsx (1 hunks)
  • apps/app/src/components/feed/form/ModerationSection.tsx (1 hunks)
  • apps/app/src/components/feed/form/RecapsSection.tsx (1 hunks)
  • apps/app/src/components/feed/form/SourcesSection.tsx (1 hunks)
  • apps/app/src/components/feed/form/StreamSettingsSection.tsx (1 hunks)
  • apps/app/src/components/feed/form/index.ts (1 hunks)
  • apps/app/src/components/feed/form/types.ts (1 hunks)
  • apps/app/src/hooks/use-edit-feed.ts (1 hunks)
  • apps/app/src/routeTree.gen.ts (4 hunks)
  • apps/app/src/routes/_layout/edit/feed.$feedId.tsx (1 hunks)
  • package.json (1 hunks)
🧰 Additional context used
🪛 GitHub Actions: CI
apps/app/src/routeTree.gen.ts

[warning] 1-1: Prettier formatting check failed. Run 'prettier --write' to fix code style issues.

🔇 Additional comments (15)
apps/app/src/components/feed/form/types.ts (2)

9-25: LGTM! Well-structured Zod schema with appropriate validation.

The schema design is solid with:

  • Required field validations for name and description
  • Reasonable minimum polling interval (1000ms)
  • Proper flattening for form handling
  • Good use of optional fields for complex configurations

The structure will work well with react-hook-form integration.


27-27: Type inference implementation is correct.

Using z.infer to generate TypeScript types from the schema ensures type safety and consistency between validation and TypeScript types.

package.json (1)

15-15: Useful addition for frontend-focused development.

The new dev:frontend script provides a convenient way to run only the frontend app using Turbo's filtering capability, which aligns well with the modular approach of the codebase.

apps/app/src/components/feed/EditFeedHeader.tsx (2)

3-6: Clean and well-typed interface.

The props interface is clear and properly typed with appropriate nullability for currentConfig.


12-14: Good fallback logic for displaying feed name.

The fallback from currentConfig?.name to feedId ensures the header always displays meaningful information, even when the config is still loading or unavailable.

apps/app/src/components/feed/form/index.ts (1)

1-7: Well-organized barrel exports for form components.

The index file provides a clean API for importing form components and types, following the standard barrel export pattern. The organization makes it easy to import multiple related components.

apps/app/src/components/feed/EditFeedActions.tsx (2)

26-40: Excellent UX implementation for save button.

The button properly handles loading states with visual feedback and disabling during mutations, providing clear user feedback.


41-56: Good implementation of destructive action button.

The delete button uses appropriate styling variants and follows the same loading state pattern as the save button, maintaining consistency.

apps/app/src/components/feed/EditFeedImageSection.tsx (1)

11-36: LGTM! Clean implementation with good UX.

The component properly handles image upload callbacks and provides user feedback through toast notifications. The conditional rendering of the initial image URL is handled correctly.

apps/app/src/components/feed/form/IngestionSection.tsx (1)

20-72: Excellent form implementation with good UX patterns.

The component correctly:

  • Uses memo for performance optimization
  • Implements conditional disabling of the schedule input based on the enabled checkbox
  • Provides clear labels and descriptions
  • Follows react-hook-form best practices

The placeholder cron expression and description help users understand the expected format.

apps/app/src/components/feed/EditFeedLoadingState.tsx (1)

27-46: LGTM! Clear error and not-found state handling.

The error and not-found states are handled appropriately with clear messaging and consistent UI patterns.

apps/app/src/routeTree.gen.ts (1)

1-672: Address Prettier formatting issue in auto-generated file.

This file is auto-generated by TanStack Router and shouldn't be manually modified. The pipeline failure indicates a Prettier formatting conflict. Consider:

  1. Adding this file to .prettierignore to exclude it from formatting checks
  2. Configuring the TanStack Router generator to match your project's formatting rules
  3. Running prettier --write on this file if it needs to be formatted
#!/bin/bash
# Check if the file is already in .prettierignore
if [ -f .prettierignore ]; then
  echo "Current .prettierignore contents:"
  cat .prettierignore
  echo ""
  echo "Checking if routeTree.gen.ts is ignored:"
  grep -E "(routeTree\.gen\.ts|\.gen\.ts)" .prettierignore || echo "Not found in .prettierignore"
else
  echo ".prettierignore file not found"
fi
apps/app/src/components/feed/form/ModerationSection.tsx (3)

26-34: Excellent state synchronization logic.

The useEffect hooks properly handle external form value changes (like form resets) while preventing infinite loops. The dependency arrays are correctly configured.

Also applies to: 70-78


46-53: Robust comma-separated value parsing.

The parsing logic correctly:

  • Splits on commas
  • Trims whitespace
  • Filters out empty values
  • Maintains the existing object structure

Also applies to: 90-97


105-121: Well-structured component with clear organization.

The main component is properly memoized and provides clear section structure with helpful descriptions for users.

name: "",
enabled: false,
schedule: "",
timezone: "UTC",
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Timezone is hardcoded without UI control.

The timezone is set to "UTC" but there's no form field to modify it. Users in different time zones might need to set their local timezone for accurate scheduling.

Would you like me to add a timezone selection field to the form?

🤖 Prompt for AI Agents
In apps/app/src/components/feed/form/RecapsSection.tsx at line 43, the timezone
is hardcoded to "UTC" without any UI control for users to change it. To fix
this, add a timezone selection field to the form that allows users to pick their
local timezone. Update the form state and submission logic to use the selected
timezone instead of the fixed "UTC" value.

Comment on lines +86 to +88
<FormLabel>Schedule (Cron)</FormLabel>
<FormControl>
<Input placeholder="0 0 * * 0" {...field} />
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add validation and helper text for cron expressions.

The cron expression field lacks validation and the placeholder might not be helpful for users unfamiliar with cron syntax. Consider adding validation and more descriptive help text.

                 <FormItem>
                   <FormLabel>Schedule (Cron)</FormLabel>
                   <FormControl>
-                    <Input placeholder="0 0 * * 0" {...field} />
+                    <Input placeholder="0 0 * * 0 (Weekly on Sunday at midnight)" {...field} />
                   </FormControl>
+                  <FormDescription>
+                    Enter a cron expression for the recap schedule
+                  </FormDescription>
                   <FormMessage />
                 </FormItem>
🤖 Prompt for AI Agents
In apps/app/src/components/feed/form/RecapsSection.tsx around lines 86 to 88,
the cron expression input lacks validation and helpful guidance. Add validation
logic to ensure the entered value is a valid cron expression, and include
descriptive helper text below the input to explain the expected format and
provide examples. This will improve user experience and prevent invalid input.

<FormControl>
<Textarea
placeholder='{"key": "value"}'
className="min-h-[100px] flex h-auto w-full rounded border border-neutral-400 bg-white px-2.5 py-2 text-base shadow-sm transition-colors placeholder:text-neutral-500 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-neutral-950 disabled:cursor-not-allowed disabled:opacity-50 md:text-base dark:border-neutral-800 dark:placeholder:text-neutral-400 dark:focus-visible:ring-neutral-300"
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Extract the repeated textarea className to a shared constant or CSS module.

The same lengthy className string for textareas is repeated multiple times across components.

Consider creating a shared constant or utility class for consistent textarea styling across the application. This could be placed in a shared styles file or UI component library.

Also applies to: 139-139

🤖 Prompt for AI Agents
In apps/app/src/components/feed/form/StreamSettingsSection.tsx at lines 83 and
139, the textarea className string is repeated verbatim. Extract this long
className string into a shared constant or a CSS module in a common styles or UI
library file. Replace the repeated className strings with a reference to this
shared constant or CSS class to ensure consistent styling and easier
maintenance.

Copy link

@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 comments (1)
apps/app/src/components/feed/form/SourcesSection.tsx (1)

1-175: Fix Prettier formatting issues before merging.

The pipeline indicates formatting issues that need to be resolved.

Run the following command to fix the formatting:

prettier --write apps/app/src/components/feed/form/SourcesSection.tsx
♻️ Duplicate comments (1)
apps/app/src/components/feed/form/SourcesSection.tsx (1)

51-102: Excellent implementation of search entry management.

The component properly handles dynamic addition/removal of search entries with good UX considerations (preventing removal of the last entry). This addresses the previous review feedback about missing search entry controls.

🧹 Nitpick comments (1)
apps/app/src/components/feed/form/SourcesSection.tsx (1)

38-44: Improve unique ID generation to prevent potential collisions.

The current ID generation using Date.now() and Math.random() may not be unique if multiple entries are added rapidly, potentially causing React key conflicts.

Consider using a more robust approach:

-            searchFieldArray.append({
-              searchId: `search-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
-              type: "",
-              query: "",
-            })
+            searchFieldArray.append({
+              searchId: crypto.randomUUID(),
+              type: "",
+              query: "",
+            })

Alternatively, create a utility function to avoid code duplication:

const generateUniqueId = () => crypto.randomUUID();
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 91f16d2 and bc40369.

📒 Files selected for processing (9)
  • apps/app/rsbuild.config.ts (1 hunks)
  • apps/app/src/components/feed/EditFeedConfigSection.tsx (1 hunks)
  • apps/app/src/components/feed/EditFeedForm.tsx (1 hunks)
  • apps/app/src/components/feed/form/BasicFieldsSection.tsx (1 hunks)
  • apps/app/src/components/feed/form/RecapsSection.tsx (1 hunks)
  • apps/app/src/components/feed/form/SourcesSection.tsx (1 hunks)
  • apps/app/src/components/feed/form/StreamSettingsSection.tsx (1 hunks)
  • apps/app/src/components/ui/textarea.tsx (1 hunks)
  • apps/app/src/hooks/use-edit-feed.ts (1 hunks)
✅ Files skipped from review due to trivial changes (2)
  • apps/app/src/components/feed/EditFeedForm.tsx
  • apps/app/src/components/feed/form/StreamSettingsSection.tsx
🚧 Files skipped from review as they are similar to previous changes (4)
  • apps/app/src/components/feed/form/RecapsSection.tsx
  • apps/app/src/hooks/use-edit-feed.ts
  • apps/app/src/components/feed/EditFeedConfigSection.tsx
  • apps/app/src/components/feed/form/BasicFieldsSection.tsx
🧰 Additional context used
🪛 GitHub Actions: CI
apps/app/src/components/feed/form/SourcesSection.tsx

[error] 1-1: Prettier formatting check failed. Run 'prettier --write' to fix code style issues.

🔇 Additional comments (4)
apps/app/src/components/feed/form/SourcesSection.tsx (4)

1-13: LGTM - Clean import structure.

The imports are well-organized and include all necessary dependencies for the component functionality.


15-28: LGTM - Proper component structure with performance optimization.

The component interface is well-defined and the use of memo is appropriate for preventing unnecessary re-renders in form contexts.


105-117: Well-designed component interface with proper abstraction.

The interface properly abstracts the field array operations and maintains good separation of concerns by only accepting the necessary methods.


141-171: Solid implementation of dynamic source management.

The component properly handles source rendering with good visual hierarchy and integrates well with the nested SearchEntries component.

Comment on lines +93 to +94
target: "https://staging.curate.press",
// target: "http://localhost:3000",
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

🧩 Verification correct

Consider the impact of switching development API target to staging.

This change redirects all local development API calls from localhost:3000 to the staging environment. While this might be necessary for testing the new feed editing features, it introduces several concerns:

  1. Network dependency: Developers now depend on staging availability for local development
  2. Data consistency: Different data between local and staging environments may cause confusion
  3. Team coordination: This affects all developers simultaneously

Consider these alternatives:

  • Use environment variables to make this configurable per developer
  • Create a separate configuration for feed editing development
  • Ensure the local backend supports the new feed editing endpoints

Verify staging environment availability and consider making this configurable:

Consider this configuration improvement to make the target environment configurable:

  server: {
    port: 5173,
    proxy: {
      "/api": {
-       target: "https://staging.curate.press",
-       // target: "http://localhost:3000",
+       target: process.env.API_PROXY_TARGET || "http://localhost:3000",
        secure: false,
        changeOrigin: true,
        ws: true,
      },
    },
  },

🏁 Script executed:

#!/bin/bash
# Description: Check staging environment availability and suggest configuration approach

# Test staging endpoint availability
echo "Testing staging environment availability..."
curl -s -o /dev/null -w "%{http_code}" "https://staging.curate.press/api/health" || echo "Staging environment check failed"

# Check if there are environment-specific configurations
echo "Checking for environment configuration patterns..."
rg -A 5 -B 5 "staging|localhost.*3000" --type ts --type js

Length of output: 3472


Consider the impact of switching development API target to staging.

This change redirects all local development API calls from localhost:3000 to the staging environment. While this might be necessary for testing the new feed editing features, it introduces several concerns:

  1. Network dependency: Developers now depend on staging availability for local development
  2. Data consistency: Different data between local and staging environments may cause confusion
  3. Team coordination: This affects all developers simultaneously

Consider these alternatives:

  • Use environment variables to make this configurable per developer
  • Create a separate configuration for feed editing development
  • Ensure the local backend supports the new feed editing endpoints

Verify staging environment availability and consider making this configurable:

#!/bin/bash
# Description: Check staging environment availability and suggest configuration approach

# Test staging endpoint availability
echo "Testing staging environment availability..."
curl -s -o /dev/null -w "%{http_code}" "https://staging.curate.press/api/health" || echo "Staging environment check failed"

# Check if there are environment-specific configurations
echo "Checking for environment configuration patterns..."
rg -A 5 -B 5 "staging|localhost.*3000" --type ts --type js

Consider this configuration improvement to make the target environment configurable:

  server: {
    port: 5173,
    proxy: {
      "/api": {
-       target: "https://staging.curate.press",
-       // target: "http://localhost:3000",
+       target: process.env.API_PROXY_TARGET || "http://localhost:3000",
        secure: false,
        changeOrigin: true,
        ws: true,
      },
    },
  },
🤖 Prompt for AI Agents
In apps/app/rsbuild.config.ts at lines 93-94, the API target is hardcoded to the
staging environment, which can cause network dependency and data consistency
issues for developers. Refactor the configuration to use environment variables
to select the API target dynamically, allowing each developer to configure their
preferred backend (localhost or staging). Implement a fallback to localhost if
no environment variable is set, and ensure the local backend supports the
necessary feed editing endpoints.

Comment on lines 12 to +13
"flex min-h-[60px] w-full rounded-md border border-neutral-200 bg-transparent px-3 py-2 text-base shadow-sm placeholder:text-neutral-500 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-neutral-950 disabled:cursor-not-allowed disabled:opacity-50 md:text-sm dark:border-neutral-800 dark:placeholder:text-neutral-400 dark:focus-visible:ring-neutral-300",
"min-h-[100px] flex h-auto w-full rounded border border-neutral-400 bg-white px-2.5 py-2 text-base shadow-sm transition-colors placeholder:text-neutral-500 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-neutral-950 disabled:cursor-not-allowed disabled:opacity-50 md:text-base dark:border-neutral-800 dark:placeholder:text-neutral-400 dark:focus-visible:ring-neutral-300",
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Remove conflicting CSS classes to prevent unpredictable styling behavior.

The code currently applies two sets of conflicting CSS classes to the textarea element. This creates conflicts for properties like min-h-[60px] vs min-h-[100px], bg-transparent vs bg-white, px-3 vs px-2.5, etc. While the last applied class typically wins, this approach is error-prone and can lead to unpredictable styling behavior.

Remove the old classes and keep only the updated styling:

      className={cn(
-        "flex min-h-[60px] w-full rounded-md border border-neutral-200 bg-transparent px-3 py-2 text-base shadow-sm placeholder:text-neutral-500 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-neutral-950 disabled:cursor-not-allowed disabled:opacity-50 md:text-sm dark:border-neutral-800 dark:placeholder:text-neutral-400 dark:focus-visible:ring-neutral-300",
        "min-h-[100px] flex h-auto w-full rounded border border-neutral-400 bg-white px-2.5 py-2 text-base shadow-sm transition-colors placeholder:text-neutral-500 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-neutral-950 disabled:cursor-not-allowed disabled:opacity-50 md:text-base dark:border-neutral-800 dark:placeholder:text-neutral-400 dark:focus-visible:ring-neutral-300",
        className,
      )}
📝 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
"flex min-h-[60px] w-full rounded-md border border-neutral-200 bg-transparent px-3 py-2 text-base shadow-sm placeholder:text-neutral-500 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-neutral-950 disabled:cursor-not-allowed disabled:opacity-50 md:text-sm dark:border-neutral-800 dark:placeholder:text-neutral-400 dark:focus-visible:ring-neutral-300",
"min-h-[100px] flex h-auto w-full rounded border border-neutral-400 bg-white px-2.5 py-2 text-base shadow-sm transition-colors placeholder:text-neutral-500 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-neutral-950 disabled:cursor-not-allowed disabled:opacity-50 md:text-base dark:border-neutral-800 dark:placeholder:text-neutral-400 dark:focus-visible:ring-neutral-300",
className={cn(
"min-h-[100px] flex h-auto w-full rounded border border-neutral-400 bg-white px-2.5 py-2 text-base shadow-sm transition-colors placeholder:text-neutral-500 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-neutral-950 disabled:cursor-not-allowed disabled:opacity-50 md:text-base dark:border-neutral-800 dark:placeholder:text-neutral-400 dark:focus-visible:ring-neutral-300",
className,
)}
🤖 Prompt for AI Agents
In apps/app/src/components/ui/textarea.tsx around lines 12 to 13, there are two
conflicting sets of CSS classes applied to the textarea element causing
unpredictable styling. Remove the first set of classes including "flex
min-h-[60px] w-full rounded-md border border-neutral-200 bg-transparent px-3
py-2 text-base shadow-sm placeholder:text-neutral-500 focus-visible:outline-none
focus-visible:ring-1 focus-visible:ring-neutral-950 disabled:cursor-not-allowed
disabled:opacity-50 md:text-sm dark:border-neutral-800
dark:placeholder:text-neutral-400 dark:focus-visible:ring-neutral-300" and keep
only the second set of updated classes to ensure consistent styling.

Comment on lines +126 to +134
onClick={() =>
appendSource({
plugin: "",
config: {},
search: [
{ searchId: `search-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`, type: "", query: "" },
],
})
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Extract duplicate ID generation logic to prevent code duplication.

This ID generation logic is duplicated from the SearchEntries component and has the same potential uniqueness issues.

Extract the ID generation to a utility function and use it consistently:

const generateUniqueId = () => crypto.randomUUID();

// Then use it here:
onClick={() =>
  appendSource({
    plugin: "",
    config: {},
    search: [
      { searchId: generateUniqueId(), type: "", query: "" },
    ],
  })
}
🤖 Prompt for AI Agents
In apps/app/src/components/feed/form/SourcesSection.tsx around lines 126 to 134,
the searchId generation logic is duplicated and may cause uniqueness issues.
Extract this ID generation into a shared utility function, for example
generateUniqueId using crypto.randomUUID(), and replace the inline ID creation
with a call to this function to ensure consistent and reliable unique IDs across
components.

@elliotBraem elliotBraem changed the base branch from main to staging June 27, 2025 16:05
@elliotBraem elliotBraem merged commit 5e4589b into staging Jun 27, 2025
4 checks passed
@elliotBraem elliotBraem deleted the feat/new-feed-edit branch June 27, 2025 22:00
@coderabbitai coderabbitai bot mentioned this pull request Jun 27, 2025
1 task
elliotBraem added a commit that referenced this pull request Jul 6, 2025
* add feed conflicts and lowercase id

* Adds "my feeds" on profile (#204)

* feat: update my feeds tab on profile page

* feat: update tabs to be routes

* fix: double scrollbar

* comment unused files in overview tab

* fix: revert rsbuild

* fmt

* fix: add routegen to prettier ignore

* clean up, server side

---------

Co-authored-by: Elliot Braem <elliot@ejlbraem.com>

* Resolve shot's comments (#205)

* feat: add name and tag validation to create

* feat: add no activity data in activity tab

* add coming soon sections for profile page

* feat: clicking on leaderboard feed hashtag will redirect to that feed

* fix: keeps name on start when disable feed names collapse

* fix: rsbuild

* fix: add routegen to prettier ignore

* fix: add ability to navigate to collapsed feeds in leaderboard

* add ability to expand or collapse all

* fix: rsbuild

* adjustments

* nitpicks

---------

Co-authored-by: Elliot Braem <elliot@ejlbraem.com>

* feat: new feed edit (#198)

* feat: update the feed editor

* feat: improve performance, and fix bugs

* feat: revert local development change

* add routegen to pretttier ignore

* fix: resolve code rabbit comments

* fix some nitpick comments

* fix prettier and build config

* formats

* merge

---------

Co-authored-by: Elliot Braem <elliot@ejlbraem.com>

* debounce

* nitpicks

* adds processing step plan

* fix auth

* Feat: recent content (#208)

* Feat: add recent feeds

* feat: add recent content to the main feed page

* fmt

* Update apps/app/src/hooks/use-rss-feed.ts

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* nitpicks

---------

Co-authored-by: Elliot Braem <elliot@everything.dev>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: Elliot Braem <elliot@ejlbraem.com>

* atuh flow

* delete old requests

---------

Co-authored-by: Zeeshan Ahmad <itexpert120@outlook.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
elliotBraem added a commit that referenced this pull request Jul 9, 2025
* add feed conflicts and lowercase id

* Adds "my feeds" on profile (#204)

* feat: update my feeds tab on profile page

* feat: update tabs to be routes

* fix: double scrollbar

* comment unused files in overview tab

* fix: revert rsbuild

* fmt

* fix: add routegen to prettier ignore

* clean up, server side

---------

Co-authored-by: Elliot Braem <elliot@ejlbraem.com>

* Resolve shot's comments (#205)

* feat: add name and tag validation to create

* feat: add no activity data in activity tab

* add coming soon sections for profile page

* feat: clicking on leaderboard feed hashtag will redirect to that feed

* fix: keeps name on start when disable feed names collapse

* fix: rsbuild

* fix: add routegen to prettier ignore

* fix: add ability to navigate to collapsed feeds in leaderboard

* add ability to expand or collapse all

* fix: rsbuild

* adjustments

* nitpicks

---------

Co-authored-by: Elliot Braem <elliot@ejlbraem.com>

* feat: new feed edit (#198)

* feat: update the feed editor

* feat: improve performance, and fix bugs

* feat: revert local development change

* add routegen to pretttier ignore

* fix: resolve code rabbit comments

* fix some nitpick comments

* fix prettier and build config

* formats

* merge

---------

Co-authored-by: Elliot Braem <elliot@ejlbraem.com>

* debounce

* nitpicks

* adds processing step plan

* fix auth

* Feat: recent content (#208)

* Feat: add recent feeds

* feat: add recent content to the main feed page

* fmt

* Update apps/app/src/hooks/use-rss-feed.ts

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* nitpicks

---------

Co-authored-by: Elliot Braem <elliot@everything.dev>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: Elliot Braem <elliot@ejlbraem.com>

* atuh flow

* delete old requests

* feat: Distributor badges link to relevant source (#210)

* add _tabs

* init with a rss feed

* xml

* fmt

---------

Co-authored-by: Zeeshan Ahmad <itexpert120@outlook.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
elliotBraem added a commit that referenced this pull request Jul 9, 2025
* add feed conflicts and lowercase id

* Adds "my feeds" on profile (#204)

* feat: update my feeds tab on profile page

* feat: update tabs to be routes

* fix: double scrollbar

* comment unused files in overview tab

* fix: revert rsbuild

* fmt

* fix: add routegen to prettier ignore

* clean up, server side

---------

Co-authored-by: Elliot Braem <elliot@ejlbraem.com>

* Resolve shot's comments (#205)

* feat: add name and tag validation to create

* feat: add no activity data in activity tab

* add coming soon sections for profile page

* feat: clicking on leaderboard feed hashtag will redirect to that feed

* fix: keeps name on start when disable feed names collapse

* fix: rsbuild

* fix: add routegen to prettier ignore

* fix: add ability to navigate to collapsed feeds in leaderboard

* add ability to expand or collapse all

* fix: rsbuild

* adjustments

* nitpicks

---------

Co-authored-by: Elliot Braem <elliot@ejlbraem.com>

* feat: new feed edit (#198)

* feat: update the feed editor

* feat: improve performance, and fix bugs

* feat: revert local development change

* add routegen to pretttier ignore

* fix: resolve code rabbit comments

* fix some nitpick comments

* fix prettier and build config

* formats

* merge

---------

Co-authored-by: Elliot Braem <elliot@ejlbraem.com>

* debounce

* nitpicks

* adds processing step plan

* fix auth

* Feat: recent content (#208)

* Feat: add recent feeds

* feat: add recent content to the main feed page

* fmt

* Update apps/app/src/hooks/use-rss-feed.ts

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* nitpicks

---------

Co-authored-by: Elliot Braem <elliot@everything.dev>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: Elliot Braem <elliot@ejlbraem.com>

* atuh flow

* delete old requests

* feat: Distributor badges link to relevant source (#210)

* add _tabs

* init with a rss feed

* xml

* fmt

* append

---------

Co-authored-by: Zeeshan Ahmad <itexpert120@outlook.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
elliotBraem added a commit that referenced this pull request Jul 9, 2025
* add feed conflicts and lowercase id

* Adds "my feeds" on profile (#204)

* feat: update my feeds tab on profile page

* feat: update tabs to be routes

* fix: double scrollbar

* comment unused files in overview tab

* fix: revert rsbuild

* fmt

* fix: add routegen to prettier ignore

* clean up, server side

---------

Co-authored-by: Elliot Braem <elliot@ejlbraem.com>

* Resolve shot's comments (#205)

* feat: add name and tag validation to create

* feat: add no activity data in activity tab

* add coming soon sections for profile page

* feat: clicking on leaderboard feed hashtag will redirect to that feed

* fix: keeps name on start when disable feed names collapse

* fix: rsbuild

* fix: add routegen to prettier ignore

* fix: add ability to navigate to collapsed feeds in leaderboard

* add ability to expand or collapse all

* fix: rsbuild

* adjustments

* nitpicks

---------

Co-authored-by: Elliot Braem <elliot@ejlbraem.com>

* feat: new feed edit (#198)

* feat: update the feed editor

* feat: improve performance, and fix bugs

* feat: revert local development change

* add routegen to pretttier ignore

* fix: resolve code rabbit comments

* fix some nitpick comments

* fix prettier and build config

* formats

* merge

---------

Co-authored-by: Elliot Braem <elliot@ejlbraem.com>

* debounce

* nitpicks

* adds processing step plan

* fix auth

* Feat: recent content (#208)

* Feat: add recent feeds

* feat: add recent content to the main feed page

* fmt

* Update apps/app/src/hooks/use-rss-feed.ts

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* nitpicks

---------

Co-authored-by: Elliot Braem <elliot@everything.dev>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: Elliot Braem <elliot@ejlbraem.com>

* atuh flow

* delete old requests

* feat: Distributor badges link to relevant source (#210)

* add _tabs

* init with a rss feed

* xml

* fmt

* append

* add service url

* adjustments

* fix

---------

Co-authored-by: Zeeshan Ahmad <itexpert120@outlook.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
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.

2 participants