Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
74e5413
Add styling for profile page
katieyungchung May 1, 2026
10b70a4
Add image drag and drop and positioning
katieyungchung May 5, 2026
d313f3c
Profile photo styling fixes
katieyungchung May 5, 2026
c95d9d0
Update input control and privacy form
katieyungchung May 5, 2026
c95cde8
Fix formatting
katieyungchung May 5, 2026
2e93cf0
Sign out button, input styling
katieyungchung May 5, 2026
b7f94af
Extract photo upload into separate component
katieyungchung May 8, 2026
7e92507
Add variant styling to photo upload component
katieyungchung May 8, 2026
917f84c
Photo upload fixes
katieyungchung May 8, 2026
c2f77b0
Change spacing for profile page
katieyungchung May 8, 2026
7d2a5c5
Image and title text styling fixes
katieyungchung May 8, 2026
d5afd5e
Separate privacy and user info and error colors
katieyungchung May 8, 2026
ea422b7
Fix submit button spacing
katieyungchung May 8, 2026
dbf4465
Update sign out button styling and format fix
katieyungchung May 8, 2026
b11a476
Update global btn-submit styling
katieyungchung May 8, 2026
57088d8
Move signout button to the left
katieyungchung May 8, 2026
6792e4c
Change btn row spacing
katieyungchung May 8, 2026
c392358
Add remove button styling
katieyungchung May 12, 2026
4a0bb33
Profile page edits
katieyungchung May 12, 2026
af6273a
Clean up code
katieyungchung May 12, 2026
44e3824
Run formatting fix
katieyungchung May 12, 2026
64305a7
Fix styling for view vs edit mode, fix up code
katieyungchung May 15, 2026
af21694
Merge remote-tracking branch 'origin/main' into profile-page-styling
katieyungchung May 15, 2026
3655f5d
Fix formatting
katieyungchung May 15, 2026
7ed43ac
Update default profile picture
katieyungchung May 15, 2026
cd5d062
Remove git line
katieyungchung May 15, 2026
3be4d91
Update profile form
katieyungchung May 15, 2026
9e629a4
Change remove button to - button for rectangle photoupload
katieyungchung May 15, 2026
1b14159
Fix wrapping for smaller window size
katieyungchung May 15, 2026
c7b9157
Change profile remove button to -
katieyungchung May 15, 2026
3a09b20
Apply styling to edit store form and put styling in module css file
katieyungchung May 15, 2026
f09bfdb
Add margin top to remove store
katieyungchung May 15, 2026
98f0626
Fix formatting
katieyungchung May 15, 2026
016c00c
Merge branch 'main' of https://github.com/lablueprint/path into profi…
joy-y-cheng May 17, 2026
c4612cf
Make styles more consistent, remove inline styling
joy-y-cheng May 17, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
99 changes: 99 additions & 0 deletions app/(main)/components/PhotoUpload.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
.wrapper {
display: flex;
flex-direction: column;
align-items: center;
position: relative;
}

.container {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
overflow: hidden;
border: 1px dashed #cbd5e0;
background: #fff;
cursor: pointer;
transition:
border-color 0.2s ease,
background 0.2s ease;
}

.container img {
width: 100%;
height: 100%;
object-fit: cover;
}

.container:hover {
border-color: #2d3748;
background: #edf2f7;
}

.container.hasPhoto {
border: none;
}

.container.dragging {
border-color: #2d3748;
background: #e2e8f0;
transform: scale(1.05);
}

.circle {
width: 12.5rem;
height: 12.5rem;
border-radius: 50%;
}

.rectangle {
width: 100%;
aspect-ratio: 1;
border-radius: 0.5rem;
}

.placeholder {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 0.25rem;
padding: 0.75rem;
text-align: center;
color: #000;
width: 100%;
height: 100%;
}

.placeholder .placeholderImage {
width: 2rem;
height: 2rem;
}

.removeButton {
position: absolute;
top: -1rem;
right: -1rem;
width: 2rem;
height: 2rem;
border-radius: 50%;
font-weight: 600;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
transition: 0.2s ease;
background-color: #ffefef;
border-color: #c53030;
border: 1px solid;
color: #c53030;
}

.removeButton:hover {
background-color: #f1c9c9;
}

.removeButtonCircle {
top: 0.8rem;
right: 0.8rem;
}
144 changes: 111 additions & 33 deletions app/(main)/components/PhotoUpload.tsx
Original file line number Diff line number Diff line change
@@ -1,55 +1,133 @@
'use client';

import { forwardRef, useImperativeHandle, useRef } from 'react';
import React from 'react';

type FileUploaderProps = {
onFileSelect: (file: File) => void;
inputRef: React.RefObject<HTMLInputElement | null>;
};

const FileUploader = ({ onFileSelect, inputRef }: FileUploaderProps) => {
const handleFileChange = (event: React.ChangeEvent<HTMLInputElement>) => {
const file = event.target.files?.[0];
if (file) {
onFileSelect(file);
}
};

return (
<input
ref={inputRef}
type="file"
accept="image/*"
onChange={handleFileChange}
/>
);
};
import { forwardRef, useImperativeHandle, useRef, useState } from 'react';
import Image from 'next/image';
import defaultProfilePhoto from '@/public/image-placeholder.svg';
import uploadPhotoIcon from '@/public/image-upload.svg';
import styles from '@/app/(main)/components/PhotoUpload.module.css';

type PhotoUploadProps = {
variant?: 'circle' | 'rectangle';
initialPhotoUrl?: string | null;
onFileSelect?: (file: File) => void;
onRemove?: () => void;
previewUrl?: string | null;
isPendingDelete?: boolean;
id?: string;
};

const PhotoUpload = forwardRef<{ resetFile: () => void }, PhotoUploadProps>(
({ onFileSelect }, ref) => {
(
{
variant = 'rectangle',
initialPhotoUrl,
onFileSelect,
onRemove,
previewUrl,
isPendingDelete,
id = 'photo-upload-input',
},
ref,
) => {
const inputRef = useRef<HTMLInputElement>(null);
const [isDragging, setIsDragging] = useState(false);

useImperativeHandle(ref, () => ({
resetFile: () => {
if (inputRef.current) {
inputRef.current.value = '';
}
if (inputRef.current) inputRef.current.value = '';
},
}));

const handleFileUpload = (file: File) => {
onFileSelect?.(file);
const handleFileChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const file = e.target.files?.[0];
if (file) onFileSelect?.(file);
};

const handleDragOver = (e: React.DragEvent) => {
e.preventDefault();
setIsDragging(true);
};

const handleDragLeave = () => setIsDragging(false);

const handleDrop = (e: React.DragEvent) => {
e.preventDefault();
setIsDragging(false);
const file = e.dataTransfer.files?.[0];
if (file?.type.startsWith('image/')) onFileSelect?.(file);
};

return <FileUploader onFileSelect={handleFileUpload} inputRef={inputRef} />;
const displayImage = isPendingDelete
? defaultProfilePhoto.src
: previewUrl || initialPhotoUrl || defaultProfilePhoto.src;

const hasPhoto = displayImage !== defaultProfilePhoto.src;

return (
<div className={styles.wrapper}>
<label
htmlFor={id}
className={[
styles.container,
styles[variant],
isDragging ? styles.dragging : '',
hasPhoto ? styles.hasPhoto : '',
].join(' ')}
onDragOver={handleDragOver}
onDragLeave={handleDragLeave}
onDrop={handleDrop}
>
{hasPhoto ? (
<Image
src={displayImage}
alt="Profile photo"
width={200}
height={200}
style={{ objectFit: 'cover' }}
unoptimized
/>
) : (
<div className={styles.placeholder}>
<Image
src={uploadPhotoIcon.src}
alt="Upload photo"
width={32}
height={32}
className={styles.placeholderImage}
unoptimized
/>
<span className={styles.photoPlaceholderText}>
Drag and drop file here or <u>browse</u>
</span>
</div>
)}
</label>

{!isPendingDelete && hasPhoto && (
<button
type="button"
onClick={onRemove}
className={[
styles.removeButton,
variant === 'circle' ? styles.removeButtonCircle : '',
].join(' ')}
>
</button>
)}

<input
ref={inputRef}
id={id}
type="file"
accept="image/*"
onChange={handleFileChange}
style={{ display: 'none' }}
/>
</div>
);
},
);

PhotoUpload.displayName = 'PhotoUpload';

export default PhotoUpload;
18 changes: 18 additions & 0 deletions app/(main)/hq/[storeId]/components/EditStoreForm.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
.layout {
display: flex;
align-items: flex-start;
gap: 3rem;
margin-bottom: 40px;
flex-wrap: wrap;
}

.photoColumn {
width: 200px;
height: 210px;
flex-shrink: 0;
}

.fieldsColumn {
flex: 1;
min-width: 0;
}
Loading
Loading