-
Notifications
You must be signed in to change notification settings - Fork 51
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
Conversation
The latest updates on your projects. Learn more about Vercel for Git ↗︎
|
WalkthroughThis 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
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
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
Possibly related PRs
Suggested reviewers
Poem
📜 Recent review detailsConfiguration used: CodeRabbit UI 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
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? 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
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)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this 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 elementsThe
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:
- Adding an appropriate aria-label to the icons
- 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 constraintsThe
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 experienceThe 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 fieldThe 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 andvideoUrlError
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:
- Add loading state during form submission
- Implement autosave functionality to prevent data loss
- 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
📒 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 positioningThe 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.
@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:
|
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:
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:
Length of output: 4756 🏁 Script executed:
Length of output: 591 🏁 Script executed:
Length of output: 1015 🏁 Script executed:
Length of output: 1132 @AndlerRL I've successfully created two GitHub issues as requested:
Both issues are now available in the repository. Would you like me to make any adjustments to either issue? |
There was a problem hiding this 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! 👍
@Bran18 |
There was a problem hiding this 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
📒 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
There was a problem hiding this 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
Project Pitch & Story UI Implementation
closes #191
Video reference
Changes Made
Key Components:
Features
Next Steps
[ ] Implement autosave
[ ] Add image upload
[ ] Enable draft saving
Summary by CodeRabbit
New Features
Chores