feat: add company logo upload functionality to job creation form - #1283

Merged
NiallJoeMaher merged 1 commit into
codu-code:developfrom
Sahejmaharjan1:feature/upload-company-logo
Oct 18, 2025
Merged

feat: add company logo upload functionality to job creation form#1283
NiallJoeMaher merged 1 commit into
codu-code:developfrom
Sahejmaharjan1:feature/upload-company-logo

Conversation

@Sahejmaharjan1

@Sahejmaharjan1Sahejmaharjan1 commented Oct 18, 2025

Copy link
Copy Markdown
Contributor

✨ 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 ownerOctober 18, 2025 13:08
@vercel

vercelBot commented Oct 18, 2025

Copy link
Copy Markdown

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

A member of the Team first needs to authorize it.

@coderabbitai

coderabbitaiBot commented Oct 18, 2025

Copy link
Copy Markdown
Contributor

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 nameStatusExplanationResolution
Docstring Coverage⚠️ WarningDocstring 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 nameStatusExplanation
Title Check✅ PassedThe 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✅ PassedThe 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
Copy Markdown

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!

@NiallJoeMaherNiallJoeMaher left a comment

Copy link
Copy Markdown
Contributor

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:developOct 18, 2025
4 of 5 checks passed

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown
Contributor

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
Copy Markdown
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.

Comment threadschema/job.ts
.url("Provide a valid url")
.optional()
.or(z.literal("")),
companyLogo: z.string().optional(),

Copy link
Copy Markdown
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 freeto 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

@Sahejmaharjan1@NiallJoeMaher
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

feat: add company logo upload functionality to job creation form - #1283

Merged
NiallJoeMaher merged 1 commit into
codu-code:developfrom
Sahejmaharjan1:feature/upload-company-logo
Oct 18, 2025
Merged

feat: add company logo upload functionality to job creation form#1283
NiallJoeMaher merged 1 commit into
codu-code:developfrom
Sahejmaharjan1:feature/upload-company-logo

Conversation

@Sahejmaharjan1

@Sahejmaharjan1Sahejmaharjan1 commented Oct 18, 2025

Copy link
Copy Markdown
Contributor

✨ 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 ownerOctober 18, 2025 13:08
@vercel

vercelBot commented Oct 18, 2025

Copy link
Copy Markdown

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

A member of the Team first needs to authorize it.

@coderabbitai

coderabbitaiBot commented Oct 18, 2025

Copy link
Copy Markdown
Contributor

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 nameStatusExplanationResolution
Docstring Coverage⚠️ WarningDocstring 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 nameStatusExplanation
Title Check✅ PassedThe 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✅ PassedThe 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
Copy Markdown

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!

@NiallJoeMaherNiallJoeMaher left a comment

Copy link
Copy Markdown
Contributor

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:developOct 18, 2025
4 of 5 checks passed

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown
Contributor

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
Copy Markdown
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.

Comment threadschema/job.ts
.url("Provide a valid url")
.optional()
.or(z.literal("")),
companyLogo: z.string().optional(),

Copy link
Copy Markdown
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 freeto 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

@Sahejmaharjan1@NiallJoeMaher
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat: add company logo upload functionality to job creation form - #1283

Merged
NiallJoeMaher merged 1 commit into
codu-code:developfrom
Sahejmaharjan1:feature/upload-company-logo
Oct 18, 2025
Merged

feat: add company logo upload functionality to job creation form#1283
NiallJoeMaher merged 1 commit into
codu-code:developfrom
Sahejmaharjan1:feature/upload-company-logo

Conversation

@Sahejmaharjan1

@Sahejmaharjan1Sahejmaharjan1 commented Oct 18, 2025

Copy link
Copy Markdown
Contributor

✨ 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 ownerOctober 18, 2025 13:08
@vercel

vercelBot commented Oct 18, 2025

Copy link
Copy Markdown

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

A member of the Team first needs to authorize it.

@coderabbitai

coderabbitaiBot commented Oct 18, 2025

Copy link
Copy Markdown
Contributor

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 nameStatusExplanationResolution
Docstring Coverage⚠️ WarningDocstring 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 nameStatusExplanation
Title Check✅ PassedThe 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✅ PassedThe 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
Copy Markdown

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!

@NiallJoeMaherNiallJoeMaher left a comment

Copy link
Copy Markdown
Contributor

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:developOct 18, 2025
4 of 5 checks passed

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown
Contributor

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
Copy Markdown
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.

Comment threadschema/job.ts
.url("Provide a valid url")
.optional()
.or(z.literal("")),
companyLogo: z.string().optional(),

Copy link
Copy Markdown
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 freeto 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

@Sahejmaharjan1@NiallJoeMaher
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat: add company logo upload functionality to job creation form - #1283

Merged
NiallJoeMaher merged 1 commit into
codu-code:developfrom
Sahejmaharjan1:feature/upload-company-logo
Oct 18, 2025
Merged

feat: add company logo upload functionality to job creation form#1283
NiallJoeMaher merged 1 commit into
codu-code:developfrom
Sahejmaharjan1:feature/upload-company-logo

Conversation

@Sahejmaharjan1

@Sahejmaharjan1Sahejmaharjan1 commented Oct 18, 2025

Copy link
Copy Markdown
Contributor

✨ 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 ownerOctober 18, 2025 13:08
@vercel

vercelBot commented Oct 18, 2025

Copy link
Copy Markdown

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

A member of the Team first needs to authorize it.

@coderabbitai

coderabbitaiBot commented Oct 18, 2025

Copy link
Copy Markdown
Contributor

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 nameStatusExplanationResolution
Docstring Coverage⚠️ WarningDocstring 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 nameStatusExplanation
Title Check✅ PassedThe 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✅ PassedThe 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
Copy Markdown

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!

@NiallJoeMaherNiallJoeMaher left a comment

Copy link
Copy Markdown
Contributor

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:developOct 18, 2025
4 of 5 checks passed

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown
Contributor

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
Copy Markdown
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.

Comment threadschema/job.ts
.url("Provide a valid url")
.optional()
.or(z.literal("")),
companyLogo: z.string().optional(),

Copy link
Copy Markdown
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 freeto 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

@Sahejmaharjan1@NiallJoeMaher
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

feat: add company logo upload functionality to job creation form - #1283

Merged
NiallJoeMaher merged 1 commit into
codu-code:developfrom
Sahejmaharjan1:feature/upload-company-logo
Oct 18, 2025
Merged

feat: add company logo upload functionality to job creation form#1283
NiallJoeMaher merged 1 commit into
codu-code:developfrom
Sahejmaharjan1:feature/upload-company-logo

Conversation

@Sahejmaharjan1

@Sahejmaharjan1Sahejmaharjan1 commented Oct 18, 2025

Copy link
Copy Markdown
Contributor

✨ 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 ownerOctober 18, 2025 13:08
@vercel

vercelBot commented Oct 18, 2025

Copy link
Copy Markdown

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

A member of the Team first needs to authorize it.

@coderabbitai

coderabbitaiBot commented Oct 18, 2025

Copy link
Copy Markdown
Contributor

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 nameStatusExplanationResolution
Docstring Coverage⚠️ WarningDocstring 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 nameStatusExplanation
Title Check✅ PassedThe 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✅ PassedThe 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
Copy Markdown

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!

@NiallJoeMaherNiallJoeMaher left a comment

Copy link
Copy Markdown
Contributor

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:developOct 18, 2025
4 of 5 checks passed

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown
Contributor

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
Copy Markdown
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.

Comment threadschema/job.ts
.url("Provide a valid url")
.optional()
.or(z.literal("")),
companyLogo: z.string().optional(),

Copy link
Copy Markdown
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 freeto 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

@Sahejmaharjan1@NiallJoeMaher
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat: add company logo upload functionality to job creation form - #1283

Merged
NiallJoeMaher merged 1 commit into
codu-code:developfrom
Sahejmaharjan1:feature/upload-company-logo
Oct 18, 2025
Merged

feat: add company logo upload functionality to job creation form#1283
NiallJoeMaher merged 1 commit into
codu-code:developfrom
Sahejmaharjan1:feature/upload-company-logo

Conversation

@Sahejmaharjan1

@Sahejmaharjan1Sahejmaharjan1 commented Oct 18, 2025

Copy link
Copy Markdown
Contributor

✨ 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 ownerOctober 18, 2025 13:08
@vercel

vercelBot commented Oct 18, 2025

Copy link
Copy Markdown

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

A member of the Team first needs to authorize it.

@coderabbitai

coderabbitaiBot commented Oct 18, 2025

Copy link
Copy Markdown
Contributor

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 nameStatusExplanationResolution
Docstring Coverage⚠️ WarningDocstring 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 nameStatusExplanation
Title Check✅ PassedThe 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✅ PassedThe 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
Copy Markdown

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!

@NiallJoeMaherNiallJoeMaher left a comment

Copy link
Copy Markdown
Contributor

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:developOct 18, 2025
4 of 5 checks passed

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown
Contributor

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
Copy Markdown
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.

Comment threadschema/job.ts
.url("Provide a valid url")
.optional()
.or(z.literal("")),
companyLogo: z.string().optional(),

Copy link
Copy Markdown
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 freeto 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

@Sahejmaharjan1@NiallJoeMaher
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat: add company logo upload functionality to job creation form - #1283

Merged
NiallJoeMaher merged 1 commit into
codu-code:developfrom
Sahejmaharjan1:feature/upload-company-logo
Oct 18, 2025
Merged

feat: add company logo upload functionality to job creation form#1283
NiallJoeMaher merged 1 commit into
codu-code:developfrom
Sahejmaharjan1:feature/upload-company-logo

Conversation

@Sahejmaharjan1

@Sahejmaharjan1Sahejmaharjan1 commented Oct 18, 2025

Copy link
Copy Markdown
Contributor

✨ 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 ownerOctober 18, 2025 13:08
@vercel

vercelBot commented Oct 18, 2025

Copy link
Copy Markdown

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

A member of the Team first needs to authorize it.

@coderabbitai

coderabbitaiBot commented Oct 18, 2025

Copy link
Copy Markdown
Contributor

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 nameStatusExplanationResolution
Docstring Coverage⚠️ WarningDocstring 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 nameStatusExplanation
Title Check✅ PassedThe 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✅ PassedThe 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
Copy Markdown

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!

@NiallJoeMaherNiallJoeMaher left a comment

Copy link
Copy Markdown
Contributor

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:developOct 18, 2025
4 of 5 checks passed

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown
Contributor

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
Copy Markdown
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.

Comment threadschema/job.ts
.url("Provide a valid url")
.optional()
.or(z.literal("")),
companyLogo: z.string().optional(),

Copy link
Copy Markdown
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 freeto 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

@Sahejmaharjan1@NiallJoeMaher
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

feat: add company logo upload functionality to job creation form - #1283

Merged
NiallJoeMaher merged 1 commit into
codu-code:developfrom
Sahejmaharjan1:feature/upload-company-logo
Oct 18, 2025
Merged

feat: add company logo upload functionality to job creation form#1283
NiallJoeMaher merged 1 commit into
codu-code:developfrom
Sahejmaharjan1:feature/upload-company-logo

Conversation

@Sahejmaharjan1

@Sahejmaharjan1Sahejmaharjan1 commented Oct 18, 2025

Copy link
Copy Markdown
Contributor

✨ 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 ownerOctober 18, 2025 13:08
@vercel

vercelBot commented Oct 18, 2025

Copy link
Copy Markdown

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

A member of the Team first needs to authorize it.

@coderabbitai

coderabbitaiBot commented Oct 18, 2025

Copy link
Copy Markdown
Contributor

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 nameStatusExplanationResolution
Docstring Coverage⚠️ WarningDocstring 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 nameStatusExplanation
Title Check✅ PassedThe 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✅ PassedThe 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
Copy Markdown

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!

@NiallJoeMaherNiallJoeMaher left a comment

Copy link
Copy Markdown
Contributor

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:developOct 18, 2025
4 of 5 checks passed

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown
Contributor

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
Copy Markdown
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.

Comment threadschema/job.ts
.url("Provide a valid url")
.optional()
.or(z.literal("")),
companyLogo: z.string().optional(),

Copy link
Copy Markdown
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 freeto 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

@Sahejmaharjan1@NiallJoeMaher