Skip to content

Conversation

@Sahejmaharjan1
Copy link
Contributor

@Sahejmaharjan1 Sahejmaharjan1 commented Oct 18, 2025

✨ Codu Pull Request 💻

Fixes #1148

Pull Request details

  • Implemented file upload for company logo with size validation (max 1MB).
  • Integrated S3 upload functionality and error handling with Sentry for logging.
  • Updated job schema to include optional companyLogo field.
  • Enhanced user feedback with toast notifications during upload process.

Any Breaking changes

  • None

Associated Screenshots

image

[Optional] What gif best describes this PR or how it makes you feel

  • None

- Implemented file upload for company logo with size validation (max 1MB).
- Integrated S3 upload functionality and error handling with Sentry for logging.
- Updated job schema to include optional companyLogo field.
- Enhanced user feedback with toast notifications during upload process.
@Sahejmaharjan1 Sahejmaharjan1 requested a review from a team as a code owner October 18, 2025 13:08
@vercel
Copy link

vercel bot commented Oct 18, 2025

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

A member of the Team first needs to authorize it.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 18, 2025

Walkthrough

Introduces a client-side logo upload feature for job creation. Users can upload a company logo with size validation, obtain a signed upload URL, and submit the file. A new optional schema field accommodates the logo data in job submissions.

Changes

Cohort / File(s) Change Summary
Client-side logo upload implementation
app/(app)/jobs/create/_client.tsx
Adds handleLogoUpload function with file size validation, signed URL retrieval, and file upload. Introduces uploadStatus state tracking (idle/loading/success/error). Disables logo button during upload and updates label dynamically. Integrates uploaded logo URL into form submission data.
Schema extension
schema/job.ts
Adds optional companyLogo: z.string() field to saveJobsSchema, expanding the type definition to include the company logo in job data validation.

Sequence Diagram

sequenceDiagram
    participant User
    participant Client as Client Component
    participant API as Backend API
    participant Storage as File Storage

    User->>Client: Select logo file
    Client->>Client: Validate file size
    alt File validation fails
        Client->>User: Show error toast
    else Validation succeeds
        Client->>Client: Set uploadStatus to loading
        Client->>API: Request signed upload URL
        API-->>Client: Return signed URL
        Client->>Storage: Upload file to signed URL
        Storage-->>Client: Upload complete
        Client->>Client: Store logo location<br/>Set uploadStatus to success
        Client->>User: Show success toast
        User->>Client: Submit job form
        Client->>API: Submit with companyLogo URL
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

The changes involve new upload handling logic with validation and error states across multiple concerns (UI state management, API interaction, form integration), plus a straightforward schema extension. Moderate complexity due to multiple interacting pieces despite affecting only two files.

Possibly related PRs

  • codu-code/codu#1106: Modifies the same client component file; this PR builds upon the UI form foundation to add functional logo upload capability.

Suggested labels

hacktoberfest-accepted, hacktoberfest

Suggested reviewers

  • John-Paul-Larkin
  • NiallJoeMaher

Poem

🐰 A logo floats up to the cloud so high,
Files validated 'neath October's sky,
Upload it, store it, submit with cheer—
Jobs now wear their company brand, dear! 📸✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Title Check ✅ Passed The PR title "feat: add company logo upload functionality to job creation form" is directly aligned with the main changes described in the changeset. The raw summary confirms that the primary objective is implementing client-side logo upload flow with size validation and schema updates to support the company logo field. The title is concise, clear, and uses standard commit message formatting without vague language. A teammate scanning the repository history would immediately understand the primary change being introduced.
Description Check ✅ Passed The PR description follows the repository's template structure and is mostly complete with well-developed content in the Pull Request details section, which comprehensively describes the implementation including file upload with size validation, S3 integration, error handling, schema updates, and user feedback features. The Breaking changes, Associated Screenshots, and optional GIF sections are all properly filled. However, the "Fixes #(issue)" line is not filled in with an actual issue number, instead retaining the placeholder text, which is a minor gap in following the template completely but does not significantly impact the clarity or completeness of what the PR accomplishes.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link

Hello @Sahejmaharjan1, thanks for opening your first Pull Request. The maintainers will review this Pull Request and provide feedback as soon as possible. Keep up the great work!

Copy link
Contributor

@NiallJoeMaher NiallJoeMaher left a comment

Choose a reason for hiding this comment

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

🌮

@NiallJoeMaher NiallJoeMaher merged commit 4b53989 into codu-code:develop Oct 18, 2025
4 of 5 checks passed
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: 2

🧹 Nitpick comments (1)
app/(app)/jobs/create/_client.tsx (1)

77-86: Add client-side file type validation before upload.

While the file input accepts only specific types (line 166), there's no validation in the handler before calling getUploadUrl. The server will reject invalid types, but this wastes bandwidth and time. Consider validating the file type against the accepted formats before initiating the upload.

Add type validation after line 81:

   const file = e.target.files[0];
   const { size, type } = file;
+
+  const acceptedTypes = ["image/png", "image/gif", "image/jpeg", "image/jpg"];
+  if (!acceptedTypes.includes(type)) {
+    setUploadStatus("error");
+    return toast.error("Invalid file type. Please upload PNG, GIF, or JPEG.");
+  }

   if (size > 1048576) {
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8c3c8b5 and 7ce06bd.

📒 Files selected for processing (2)
  • app/(app)/jobs/create/_client.tsx (3 hunks)
  • schema/job.ts (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
app/(app)/jobs/create/_client.tsx (4)
schema/job.ts (1)
  • saveJobsInput (33-33)
app/actions/getUploadUrl.ts (1)
  • getUploadUrl (15-44)
utils/s3helpers.ts (1)
  • uploadFile (17-28)
app/(app)/settings/_client.tsx (3)
  • onSuccess (139-150)
  • signedUrl (107-123)
  • onError (133-138)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: e2e
🔇 Additional comments (3)
app/(app)/jobs/create/_client.tsx (3)

64-70: Good integration of companyLogo into form submission.

The form data correctly includes the uploaded logo URL using the imgUrl state, with proper handling of null values.


88-110: Solid upload flow with proper error handling.

The upload logic correctly obtains a signed URL, uploads the file, and validates the response at each step with appropriate error messages.


158-161: Excellent UX improvements with upload state feedback.

The button correctly disables during upload and shows dynamic text ("Uploading..." vs "Change Logo"), providing clear feedback to users.

Comment on lines +72 to 125
const handleLogoUpload = async (e: React.ChangeEvent<HTMLInputElement>) => {
if (uploadStatus === "loading") {
return toast.info("Upload in progress, please wait...");
}

if (e.target.files && e.target.files.length > 0) {
setUploadStatus("loading");

const file = e.target.files[0];
const { size, type } = file;

if (size > 1048576) {
setUploadStatus("error");
return toast.error("File size too big (max 1MB).");
}

try {
const res = await getUploadUrl({
size,
type,
uploadType: "uploads",
});

const signedUrl = res?.data;

if (!signedUrl) {
setUploadStatus("error");
return toast.error(
"Something went wrong uploading the logo, please retry.",
);
}

const { fileLocation } = await uploadFile(signedUrl, file);
if (!fileLocation) {
setUploadStatus("error");
return toast.error(
"Something went wrong uploading the logo, please retry.",
);
}

setUploadStatus("success");
setImgUrl(fileLocation);
toast.success("Company logo uploaded successfully!");
} catch (error) {
setUploadStatus("error");
toast.error(
error instanceof Error
? error.message
: "An error occurred while uploading the logo.",
);
Sentry.captureException(error);
}
}
};
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

File input should be reset after upload to allow re-uploading the same file.

After a successful (or failed) upload, the file input retains its value. If a user attempts to upload the same file again, the onChange event won't fire because the input value hasn't changed.

Add input reset after setting upload status:

   try {
     const res = await getUploadUrl({
       size,
       type,
       uploadType: "uploads",
     });

     const signedUrl = res?.data;

     if (!signedUrl) {
       setUploadStatus("error");
+      if (fileInputRef.current) fileInputRef.current.value = "";
       return toast.error(
         "Something went wrong uploading the logo, please retry.",
       );
     }

     const { fileLocation } = await uploadFile(signedUrl, file);
     if (!fileLocation) {
       setUploadStatus("error");
+      if (fileInputRef.current) fileInputRef.current.value = "";
       return toast.error(
         "Something went wrong uploading the logo, please retry.",
       );
     }

     setUploadStatus("success");
     setImgUrl(fileLocation);
+    if (fileInputRef.current) fileInputRef.current.value = "";
     toast.success("Company logo uploaded successfully!");
   } catch (error) {
     setUploadStatus("error");
+    if (fileInputRef.current) fileInputRef.current.value = "";
     toast.error(

Committable suggestion skipped: line range outside the PR's diff.

.url("Provide a valid url")
.optional()
.or(z.literal("")),
companyLogo: z.string().optional(),
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major

Add URL validation to the companyLogo field.

The companyLogo field should validate URL format for consistency with applicationUrl (lines 21-25) and to ensure only valid URLs are stored.

Apply this diff:

-  companyLogo: z.string().optional(),
+  companyLogo: z.string().url("Provide a valid logo URL").optional().or(z.literal("")),

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In schema/job.ts around line 26, the companyLogo field currently allows any
string; update its schema to validate URLs like applicationUrl does. Replace the
current definition with a string URL validator and keep it optional (e.g., use
the same z.string().url().optional() pattern as applicationUrl) so only valid
URL values are accepted and existing optional semantics are preserved.

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.

Image Upload Functionality Not Implemented for Company Logo in Jobs Create page

2 participants