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

Feat/pitch and story view #220

Merged
merged 7 commits into from
Feb 27, 2025
Merged

Feat/pitch and story view #220

merged 7 commits into from
Feb 27, 2025

Conversation

evgongora
Copy link
Collaborator

@evgongora evgongora commented Feb 26, 2025

Project Pitch & Story UI Implementation

closes #191

Video reference

Changes Made

  1. Implemented project pitch page with story editor and media uploads
  2. Added rich text editor with formatting tools
  3. Created sidebar with writing tips and pro guidance
  4. Integrated file upload for pitch decks (PDF/PPTX)

Key Components:

  • ProjectStoryForm: Title + rich text editor
  • ProjectMedia: File upload + video URL
  • ProjectTips: Writing guidance
  • RichTextEditor: Formatting tools

Features

  • Rich text formatting (bold, italic, headings, lists)
  • Drag & drop file upload (10MB limit)
  • Video URL support (YouTube/Vimeo)
  • Character counter for title
  • Responsive layout
  • Error handling

Next Steps

[ ] Implement autosave
[ ] Add image upload
[ ] Enable draft saving

Summary by CodeRabbit

  • New Features

    • Enhanced client-side functionality for a smoother and more responsive experience.
    • Introduced an interactive project pitch page featuring a media upload area with drag-and-drop support, a dedicated form for story submissions with live validation, and rich text editing capabilities.
    • Added a dedicated section offering writing tips and guidance to improve pitch clarity.
    • New components for media uploads, story submissions, and rich text editing to enhance user interaction.
  • Chores

    • Upgraded core libraries to bolster advanced text editing and file handling features.

Copy link

vercel bot commented Feb 26, 2025

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

Name Status Preview Comments Updated (UTC)
kindfi ✅ Ready (Inspect) Visit Preview 💬 Add feedback Feb 27, 2025 3:55am

Copy link
Contributor

coderabbitai bot commented Feb 26, 2025

Walkthrough

This pull request adds a client-side directive to an existing input file and introduces several new components across the project. New components include those for media handling, story submission, writing tips, and rich text editing. A new validation schema is also defined for project stories. Additionally, the dependency list is updated to include Tiptap editor packages and react-dropzone while removing unused libraries. The new page component integrates these features for a comprehensive project pitch experience.

Changes

File(s) Summary
apps/web/components/base/input.tsx Added the 'use client' directive to indicate client-side execution.
apps/web/components/sections/project/project-media.tsx,
project-story.tsx,
project-tips.tsx,
rich-text-editor.tsx
Introduced new React components: ProjectMedia, ProjectStoryForm, ProjectTips, and RichTextEditor for handling media uploads, story submissions, displaying tips, and rich text editing respectively.
apps/web/lib/validators/project.ts Added a new validation schema (projectStorySchema) and corresponding ProjectStory type using Zod for validating project story data.
apps/web/package.json Added new dependencies for Tiptap editor extensions and react-dropzone; removed html-react-parser, pdfjs-dist, and tesseract.js to streamline library usage.
apps/web/app/(routes)/project/[id]/story/page.tsx Created a new ProjectPitchPage component that integrates the story form, media management, and writing tips, with handlers for story submission, file uploads, video URL changes, and saving all changes.

Sequence Diagram(s)

sequenceDiagram
    participant U as User
    participant P as ProjectPitchPage
    participant S as ProjectStoryForm
    participant M as ProjectMedia
    participant T as ProjectTips

    U->>P: Fill in project story details
    P->>S: Validate and capture story input
    S-->>P: Return validated story data
    U->>P: Upload file/enter video URL
    P->>M: Process media inputs
    U->>P: Interact with writing tips (optional)
    P->>T: Display guidance and tips
    U->>P: Click "Save All"
    P->>U: Confirm submission of pitch
Loading
sequenceDiagram
    participant U as User
    participant R as RichTextEditor
    participant E as Tiptap Editor

    U->>R: Enter or format text
    R->>E: Forward command for formatting/update
    E-->>R: Trigger onUpdate callback with new content
    R->>U: Display updated formatted text
Loading

Possibly related PRs

Suggested reviewers

  • AndlerRL

Poem

In code we weave a tale so bright,
With client cues and forms just right.
Media uploads and stories told,
Rich text edits in styles bold.
Happy bytes, let features flow—
🚀 Cheers to changes that help us grow!

Consider the flow, enhance with might!


📜 Recent review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 3ea329c and d1a269a.

📒 Files selected for processing (1)
  • apps/web/package.json (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/web/package.json

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 generate docstrings to generate docstrings for 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.

@coderabbitai coderabbitai bot added documentation enhancement New feature improvement or request TL TL Related webapp web app related labels Feb 26, 2025
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: 7

🧹 Nitpick comments (9)
apps/web/components/sections/project/project-tips.tsx (1)

4-41: Well-structured component with good UI elements

The ProjectTips component is well-organized and provides valuable writing guidance to users. I appreciate the use of icons and card components to create an engaging visual experience.

Consider enhancing the accessibility of this component by:

  1. Adding an appropriate aria-label to the icons
  2. Including a more descriptive key for the mapped list items (currently using the tip text as key)
- <Star className="w-5 h-5 text-yellow-500" />
+ <Star className="w-5 h-5 text-yellow-500" aria-hidden="true" />

- <li key={tip} className="flex items-start gap-2">
+ <li key={`writing-tip-${tip.substring(0, 10)}`} className="flex items-start gap-2">

Additionally, consider adding a small animation to the hover effect to further enhance the interactive experience.

apps/web/lib/validators/project.ts (2)

148-171: Well-structured validation schema with good constraints

The projectStorySchema provides a solid foundation for form validation. The constraints for title length, file size, and URL validation are appropriately defined.

Consider enhancing the story field validation with minimum and maximum length requirements similar to other text fields in the existing schemas:

- story: z.string().min(1, 'Story is required'),
+ story: z.string().min(1, 'Story is required').max(10000, 'Story must be less than 10,000 characters'),

Additionally, for the video URL validation, consider making the error message more helpful by suggesting the supported platforms:

- 'Must be a YouTube or Vimeo URL',
+ 'Please enter a valid YouTube or Vimeo URL (e.g., https://youtube.com/watch?v=... or https://vimeo.com/...)',

155-159: Enhance pitchDeck validation for better user experience

The pitchDeck validation is good but could be improved for better user feedback. Consider making the url field required when a file is uploaded and adding a name field to store the original filename:

pitchDeck: z
 .object({
-	url: z.string().optional(),
+	url: z.string().min(1, 'File URL is required'),
+	name: z.string().min(1, 'Filename is required'),
 	size: z.number().max(10 * 1024 * 1024, 'File must be less than 10MB'),
 })
 .optional(),

This will ensure that when a file is uploaded, all necessary information is captured.

apps/web/components/sections/project/project-media.tsx (1)

67-79: Add validation feedback for the video URL field

The current video URL input doesn't provide visual feedback to users about the validity of their input. Consider enhancing the input with validation indicators:

<div>
  <h4 className="font-medium mb-2">Video URL</h4>
  <Input
    type="url"
    placeholder="Enter URL to your pitch video (YouTube, Vimeo, etc.)"
    value={videoUrl}
    onChange={(e) => onVideoUrlChange(e.target.value)}
-   className="w-full"
+   className={`w-full ${videoUrlError ? 'border-red-500' : videoUrl && isValidVideoUrl(videoUrl) ? 'border-green-500' : ''}`}
  />
+ {videoUrlError && <p className="text-sm text-red-500 mt-1">{videoUrlError}</p>}
  <p className="text-sm text-gray-500 mt-1">
    Optional: Add a video to enhance your pitch
  </p>
</div>

You'll need to implement the isValidVideoUrl function and videoUrlError state to make this work properly.

apps/web/components/sections/project/rich-text-editor.tsx (3)

22-26: Clean and well-typed props interface.

The props interface is clear and follows good TypeScript practices. Consider adding JSDoc comments to provide more context about each prop's purpose and expected format, especially for the content string which could be HTML.

 interface RichTextEditorProps {
+  /** HTML content to display in the editor */
   content: string
+  /** Callback triggered when editor content changes */
   onChange: (content: string) => void
+  /** Optional placeholder text when editor is empty */
   placeholder?: string
 }

33-80: Great editor configuration with well-defined styling.

The editor configuration is comprehensive with appropriate styling for various elements. The HTML attributes with Tailwind classes ensure consistent styling within your design system.

Consider adding keyboard shortcuts information and improving accessibility:

 const editor = useEditor({
   extensions: [
     StarterKit.configure({
       heading: {
         levels: [1, 2],
+        // Define keyboard shortcuts
+        // Level 1: Ctrl+Alt+1, Level 2: Ctrl+Alt+2
       },
       // other configurations...
     }),
     // other extensions...
   ],
   content,
   onUpdate: ({ editor }) => {
     onChange(editor.getHTML())
   },
   editorProps: {
     attributes: {
       class:
         'prose prose-sm focus:outline-none max-w-none min-h-[200px] [&_h1]:text-3xl [&_h1]:font-bold [&_h1]:mb-4 [&_h2]:text-2xl [&_h2]:font-semibold [&_h2]:mb-3 [&_ul]:list-disc [&_ul]:ml-4 [&_ol]:list-decimal [&_ol]:ml-4 [&_li]:ml-2 [&_li]:pl-1 [&_p]:mb-2 [&_p:last-child]:mb-0',
+      role: 'textbox',
+      'aria-multiline': 'true',
+      'aria-label': 'Rich text editor',
     },
   },
 })

86-203: Well-structured editor toolbar with proper styling.

The toolbar implementation has good organization and consistent styling. The active state indicators provide good visual feedback to users.

Consider adding tooltips to explain the purpose of each button for better usability:

 <Button
   variant="outline"
   size="icon"
   onClick={() => editor.chain().focus().toggleBold().run()}
   className={cn(
     'transition-colors',
     editor.isActive('bold') && 'bg-accent text-accent-foreground',
   )}
+  aria-label="Bold"
+  title="Bold (Ctrl+B)"
 >
   <Bold className="h-4 w-4" />
 </Button>
apps/web/components/sections/project/project-story.tsx (2)

38-72: Consider adding form submission feedback and autosave.

The form implementation is clean and well-structured. Consider enhancing the user experience with the following improvements:

  1. Add loading state during form submission
  2. Implement autosave functionality to prevent data loss
  3. Add a submit button to make the form's action more explicit
 <form onSubmit={handleSubmit(onSubmit)} className="space-y-6">
   <Card className="p-6 shadow-md hover:shadow-lg transition-shadow">
     <h3 className="text-xl font-semibold mb-4">Project Story</h3>
     <div className="space-y-4">
       {/* Input fields... */}
     </div>
+    <div className="flex justify-end mt-6">
+      <Button type="submit" className="px-6">
+        Save Story
+      </Button>
+    </div>
   </Card>
 </form>

For autosave, consider implementing a debounced save function:

// Import at the top
import { useCallback, useEffect } from 'react'
import { debounce } from 'your-utility-library-or-lodash'

// Inside component
const debouncedSave = useCallback(
  debounce((data: ProjectStory) => {
    // Call API or store data locally
    console.log('Autosaving...', data)
  }, 2000),
  []
)

// Watch for changes and trigger autosave
const formData = watch()
useEffect(() => {
  if (formData.title || formData.story) {
    debouncedSave(formData as ProjectStory)
  }
}, [formData, debouncedSave])

59-62: Provide feedback when content is being saved.

When the RichTextEditor content changes, consider providing visual feedback to users that their changes are being saved or tracked. This could be a small indicator or status message.

 <RichTextEditor
   content={initialData?.story || ''}
   onChange={(content) => {
     setValue('story', content)
+    // Add visual feedback that content is being saved
+    // This could be implemented with a state variable
+    setIsSaving(true)
+    // After a delay, set it back to false
+    setTimeout(() => setIsSaving(false), 1000)
   }}
 />
+{isSaving && (
+  <p className="text-xs text-gray-500 mt-1">Saving changes...</p>
+)}
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 1d45310 and a6d95e0.

📒 Files selected for processing (11)
  • apps/web/app/project/pitch/page.tsx (1 hunks)
  • apps/web/components/base/button.tsx (1 hunks)
  • apps/web/components/base/input.tsx (1 hunks)
  • apps/web/components/sections/project/project-media.tsx (1 hunks)
  • apps/web/components/sections/project/project-story.tsx (1 hunks)
  • apps/web/components/sections/project/project-tips.tsx (1 hunks)
  • apps/web/components/sections/project/rich-text-editor.tsx (1 hunks)
  • apps/web/components/shared/kyc/kyc-5/final-review.tsx (1 hunks)
  • apps/web/lib/types/final-review-kyc5.types.ts (1 hunks)
  • apps/web/lib/validators/project.ts (1 hunks)
  • apps/web/package.json (2 hunks)
✅ Files skipped from review due to trivial changes (4)
  • apps/web/components/shared/kyc/kyc-5/final-review.tsx
  • apps/web/components/base/input.tsx
  • apps/web/components/base/button.tsx
  • apps/web/lib/types/final-review-kyc5.types.ts
🧰 Additional context used
📓 Path-based instructions (1)
`**/*.ts`: Review TypeScript files ensuring type safety with...

**/*.ts: Review TypeScript files ensuring type safety with no 'any' usage unless justified. Verify named exports, proper error handling with typed errors, and pure functions. Check module encapsulation and consistent naming using camelCase for functions and PascalCase for types. Validate unit test coverage for utilities if required.

  • apps/web/lib/validators/project.ts
🔇 Additional comments (7)
apps/web/components/sections/project/project-tips.tsx (1)

6-6: Consider testing responsive behavior of sticky positioning

The sticky positioning looks good for desktop views, but you might want to verify how it behaves on smaller screens and different viewport heights.

Consider adding responsive adjustments to the sticky behavior:

- <div className="space-y-6 sticky top-24">
+ <div className="space-y-6 md:sticky top-24">

This would disable the sticky behavior on mobile screens where it might cause issues with scrolling or content visibility.

apps/web/components/sections/project/rich-text-editor.tsx (1)

3-21: Well-structured imports with good organization.

The component has well-organized imports with clear separation between external libraries and internal components. The Tiptap ecosystem is properly utilized alongside Lucide icons.

apps/web/package.json (2)

40-45: Good alignment of Tiptap package versions.

All Tiptap packages are using the same version (2.11.5), which helps maintain consistency and avoid compatibility issues. This is a good practice for related packages.


63-63: Added react-dropzone for file upload functionality.

The addition of react-dropzone aligns with the PR objectives for implementing media upload functionality. This is a popular and well-maintained library for handling file uploads with drag-and-drop support.

apps/web/components/sections/project/project-story.tsx (3)

3-12: Well-structured imports with good separation.

The imports are organized clearly, separating external libraries from internal components. The explicit type import from the validators shows good TypeScript practices.


13-16: Clear and typed props interface.

The props interface is well-defined with appropriate types. The optional initialData prop allows for flexible reuse of the component for both creation and editing scenarios.


28-34: Good form setup with Zod validation.

Using zodResolver with react-hook-form is an excellent approach for type-safe form validation. The defaultValues setup with fallbacks to empty strings is also a good practice.

@AndlerRL
Copy link
Member

@coderabbitai I am looking now the review notes and checking the issue list, we are not having the table for the project pitch. Proceed to create the issue and add the related issues for reference. Ensure to add the fields that are within this new UI form:

  1. title
  2. description
  3. pitch_deck: reference from the supabase buckets. We have to create another issue that creates the bucket configuration and RLS policies here.
  4. video_url
  5. project_id: reference from the projects table

Copy link
Contributor

coderabbitai bot commented Feb 26, 2025

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

@AndlerRL I've created two GitHub issues based on your requirements:

  1. Issue: Create 'project_pitch' table in database schema

  2. Issue: Configure Supabase bucket and RLS policies for project pitch deck files

    • Created a separate issue for the bucket configuration as requested
    • Included RLS policies to ensure secure access to files
    • Specified 10MB file size limit as implemented in the UI

Both issues have been linked to the related issue #191 for better tracking and context. Let me know if you need any adjustments to either issue!


🏁 Script executed:

#!/bin/bash
# Search for issues related to project pitch, database tables, or Supabase buckets
echo "Searching for issues related to project pitch..."
gh issue list --search "project pitch" --limit 5

echo -e "\nSearching for issues related to database tables..."
gh issue list --search "database table" --limit 5

echo -e "\nSearching for issues related to Supabase buckets..."
gh issue list --search "supabase bucket" --limit 5

echo -e "\nSearching for issue #191 (mentioned in PR description)..."
gh issue view 191

echo -e "\nGet PR description for more context"
gh pr view 220

Length of output: 4756


🏁 Script executed:

#!/bin/bash
# Check if there's already a database schema file to understand the database structure
echo "Searching for database schema files..."
fd --type f --glob "*.sql" | grep -i schema

echo -e "\nSearching for any Supabase configuration files..."
fd supabase --type d

# Look for any existing project table structure
echo -e "\nSearching for project table mentions in code..."
rg "projects table|projects schema|project table" --type-add 'sql:*.{sql}' --type sql -A 5 -B 5

Length of output: 591


🏁 Script executed:

#!/bin/bash
# Create the issue for the project pitch table
gh issue create \
  --title "Create 'project_pitch' table in database schema" \
  --body "## Overview
We need to create a database table to store the project pitch data. The UI has been implemented in PR #220, but we need a corresponding database table to store the information.

## Requirements

### Table: project_pitch
- **title**: string - The title of the project pitch
- **description**: text - The rich text description/story of the project
- **pitch_deck**: string - Reference to file in Supabase bucket
- **video_url**: string - URL to video (YouTube, Vimeo)
- **project_id**: uuid - Foreign key reference to projects table

## Related Issues
- #191 - Implement project pitch page with story editor and media upload (addressed in PR #220)

## Notes
- The project pitch UI has been implemented in PR #220
- We need to create a new table in the database schema
- A separate issue will be created for the Supabase bucket configuration to store pitch deck files"

Length of output: 1015


🏁 Script executed:

#!/bin/bash
# Create the issue for the Supabase bucket configuration and RLS policies
gh issue create \
  --title "Configure Supabase bucket and RLS policies for project pitch deck files" \
  --body "## Overview
We need to configure a Supabase bucket to store project pitch deck files uploaded through the project pitch page. We also need to implement Row Level Security (RLS) policies to ensure secure access to these files.

## Requirements

1. Create a new Supabase bucket called 'project_pitch_decks'
2. Configure appropriate content types (PDF, PPT, etc.)
3. Set up RLS policies to:
   - Allow authenticated users to upload files to their own projects
   - Allow only project owners and collaborators to view files
   - Prevent unauthorized access and deletion

## Related Issues
- Issue for creating the 'project_pitch' table (to be linked once created)
- #191 - Implement project pitch page with story editor and media upload (addressed in PR #220)

## Notes
- The UI for file uploads has been implemented in PR #220
- The project_pitch table will reference files stored in this bucket
- Maximum file size should be limited to 10MB as implemented in the UI"

Length of output: 1132


@AndlerRL I've successfully created two GitHub issues as requested:

  1. Issue Create 'project_pitch' table in database schema #225: Create 'project_pitch' table in database schema

  2. Issue Configure Supabase bucket and RLS policies for project pitch deck files #226: Configure Supabase bucket and RLS policies for project pitch deck files

    • Specifies creating a 'project_pitch_decks' bucket with proper content types
    • Details RLS policies for secure access
    • Includes the 10MB file size limit as implemented in the UI
    • References issue Create "Pitch & Story" View #191 and mentions the related project_pitch table issue

Both issues are now available in the repository. Would you like me to make any adjustments to either issue?

Copy link
Member

@AndlerRL AndlerRL left a comment

Choose a reason for hiding this comment

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

LGTM! However, I found some observations made by the AI and @Bran18. Please take them a look and we should be good to go! 👍

@evgongora
Copy link
Collaborator Author

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: 1

🧹 Nitpick comments (4)
apps/web/app/(routes)/project/[id]/story/page.tsx (4)

1-7: Great job structuring your imports, consider using path aliases.

The imports are well-organized by functionality, which enhances readability. Consider using path aliases (e.g., @components, @lib) to avoid deep relative paths like '../../../../../'. This would make the code more maintainable and resilient to refactoring.

-import { Save } from 'lucide-react'
-import { Button } from '../../../../../components/base/button'
-import { ProjectMedia } from '../../../../../components/sections/project/project-media'
-import { ProjectStoryForm } from '../../../../../components/sections/project/project-story'
-import { ProjectTips } from '../../../../../components/sections/project/project-tips'
-import type { ProjectStory } from '../../../../../lib/validators/project'
+import { Save } from 'lucide-react'
+import { Button } from '@components/base/button'
+import { ProjectMedia } from '@components/sections/project/project-media'
+import { ProjectStoryForm } from '@components/sections/project/project-story'
+import { ProjectTips } from '@components/sections/project/project-tips'
+import type { ProjectStory } from '@lib/validators/project'

9-27: Nice placeholder functions with TODOs, consider implementing state management.

The handler functions provide clear placeholders for future implementation. We could enhance this by adding appropriate state management and error handling to make these functions fully functional.

+import { useState } from 'react'
+
 export default function ProjectPitchPage() {
+  const [isLoading, setIsLoading] = useState(false)
+  const [error, setError] = useState<string | null>(null)
+  const [story, setStory] = useState<ProjectStory | null>(null)
+  const [file, setFile] = useState<File | null>(null)
+  const [videoUrl, setVideoUrl] = useState<string>('')
+
   const handleStorySubmit = (data: ProjectStory) => {
     // TODO: Implement story submission
     console.log('Story submitted:', data)
+    setStory(data)
   }

   const handleFileUpload = (file: File) => {
     // TODO: Implement file upload
     console.log('File uploaded:', file.name)
+    setFile(file)
   }

   const handleVideoUrlChange = (url: string) => {
     // TODO: Implement video URL update
     console.log('Video URL updated:', url)
+    setVideoUrl(url)
   }

   const handleSaveAll = () => {
+    setIsLoading(true)
+    setError(null)
     // TODO: Implement saving all changes
     console.log('Saving all changes')
+    try {
+      // API call would go here
+      setTimeout(() => {
+        setIsLoading(false)
+      }, 1000)
+    } catch (err) {
+      setError('Failed to save changes')
+      setIsLoading(false)
+    }
   }

36-54: Well-structured layout with responsive design, consider adding feedback states.

The grid layout with responsive columns is excellent. We could enhance the user experience by adding loading and error states to provide feedback during operations.

 <div className="grid grid-cols-1 lg:grid-cols-4 gap-8">
   <div className="lg:col-span-3">
+    {error && (
+      <div className="bg-red-50 border border-red-200 text-red-800 rounded-md p-4 mb-4">
+        {error}
+      </div>
+    )}
     <div className="space-y-8">
       <ProjectStoryForm onSubmit={handleStorySubmit} />
       <ProjectMedia
         onFileUpload={handleFileUpload}
         onVideoUrlChange={handleVideoUrlChange}
       />
     </div>
     <div className="mt-8 flex justify-end">
       <Button
         onClick={handleSaveAll}
+        disabled={isLoading}
         className="bg-black hover:bg-black/90 text-white"
       >
-        <Save className="w-4 h-4 mr-1" />
-        Save Changes
+        {isLoading ? (
+          <>
+            <span className="animate-spin h-4 w-4 mr-2 border-2 border-white border-t-transparent rounded-full" />
+            Saving...
+          </>
+        ) : (
+          <>
+            <Save className="w-4 h-4 mr-1" />
+            Save Changes
+          </>
+        )}
       </Button>
     </div>
   </div>

29-62: Great semantic HTML structure, consider adding persistence for user data.

The layout is well-organized with appropriate HTML semantics. For a better user experience, consider implementing a mechanism to persist form data during navigation or page refreshes to prevent data loss.

+import { useEffect } from 'react'
+
 export default function ProjectPitchPage() {
+  // ... state management code from previous suggestion
+
+  // Load saved data from localStorage on component mount
+  useEffect(() => {
+    const savedData = localStorage.getItem('projectPitchDraft')
+    if (savedData) {
+      try {
+        const { story, videoUrl } = JSON.parse(savedData)
+        if (story) setStory(story)
+        if (videoUrl) setVideoUrl(videoUrl)
+      } catch (e) {
+        console.error('Failed to parse saved draft data')
+      }
+    }
+  }, [])
+
+  // Save data to localStorage when it changes
+  useEffect(() => {
+    if (story || videoUrl) {
+      localStorage.setItem(
+        'projectPitchDraft',
+        JSON.stringify({ story, videoUrl })
+      )
+    }
+  }, [story, videoUrl])
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between a6d95e0 and 3ea329c.

📒 Files selected for processing (2)
  • apps/web/app/(routes)/project/[id]/story/page.tsx (1 hunks)
  • apps/web/package.json (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/web/package.json

coderabbitai[bot]
coderabbitai bot previously approved these changes Feb 27, 2025
Copy link
Contributor

@Bran18 Bran18 left a comment

Choose a reason for hiding this comment

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

✅ PR Approved – Great Job! 🎉

Congratulations on completing this issue! You did an excellent job, and we truly appreciate your contribution to KindFi. 🚀

I’ve fixed the build issues and also created new issues to address the suggestions from the AI. Feel free to check them out if you’d like to continue contributing!

We can’t wait to see more of your work in future contributions. Keep up the great effort! 💪

Best,
The KindFi Team

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature improvement or request TL TL Related webapp web app related
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Create "Pitch & Story" View
3 participants