feat(settings): add avatar profile color palette selection
All checks were successful
Deploy Waveform to VPS / deploy (push) Successful in 1m18s
All checks were successful
Deploy Waveform to VPS / deploy (push) Successful in 1m18s
This commit is contained in:
parent
6b104d112d
commit
d2f3d30d20
1 changed files with 40 additions and 3 deletions
|
|
@ -8,8 +8,11 @@
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { UserAvatar } from "@/components/ui/UserAvatar";
|
import { UserAvatar } from "@/components/ui/UserAvatar";
|
||||||
import { UserStatus, User } from "@/db/schema";
|
import { UserStatus, User } from "@/db/schema";
|
||||||
import { MEMBER_STATUS_COLOR_CLASSES } from "@/lib/constants/member.styles";
|
import {
|
||||||
import { UserRound } from "lucide-react";
|
MEMBER_STATUS_COLOR_CLASSES,
|
||||||
|
MEMBER_COLOR_OPTIONS,
|
||||||
|
} from "@/lib/constants/member.styles";
|
||||||
|
import { UserRound, Palette } from "lucide-react";
|
||||||
|
|
||||||
/** Props for the SettingsView component. */
|
/** Props for the SettingsView component. */
|
||||||
interface SettingsViewProps {
|
interface SettingsViewProps {
|
||||||
|
|
@ -17,11 +20,14 @@ interface SettingsViewProps {
|
||||||
currentUser: User;
|
currentUser: User;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Renders the user settings view for profile management and status selection. */
|
/** Renders the user settings view for profile management, status selection, and avatar color customization. */
|
||||||
export function SettingsView({ userId, currentUser }: SettingsViewProps) {
|
export function SettingsView({ userId, currentUser }: SettingsViewProps) {
|
||||||
const [selectedStatus, setSelectedStatus] = useState<UserStatus>(
|
const [selectedStatus, setSelectedStatus] = useState<UserStatus>(
|
||||||
currentUser.status,
|
currentUser.status,
|
||||||
);
|
);
|
||||||
|
const [selectedColor, setSelectedColor] = useState<string>(
|
||||||
|
currentUser.color || MEMBER_COLOR_OPTIONS[0],
|
||||||
|
);
|
||||||
|
|
||||||
const statuses: { label: string; value: UserStatus }[] = [
|
const statuses: { label: string; value: UserStatus }[] = [
|
||||||
{ label: "Online", value: "ONLINE" },
|
{ label: "Online", value: "ONLINE" },
|
||||||
|
|
@ -35,11 +41,17 @@ export function SettingsView({ userId, currentUser }: SettingsViewProps) {
|
||||||
setSelectedStatus(newStatus);
|
setSelectedStatus(newStatus);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** Updates local avatar color state on user selection. */
|
||||||
|
const handleColorChange = (newColor: string) => {
|
||||||
|
setSelectedColor(newColor);
|
||||||
|
};
|
||||||
|
|
||||||
if (!currentUser) return null;
|
if (!currentUser) return null;
|
||||||
|
|
||||||
const userWithUpdatedSettings = {
|
const userWithUpdatedSettings = {
|
||||||
...currentUser,
|
...currentUser,
|
||||||
status: selectedStatus,
|
status: selectedStatus,
|
||||||
|
color: selectedColor,
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
@ -94,6 +106,31 @@ export function SettingsView({ userId, currentUser }: SettingsViewProps) {
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/* Color Palette Selection */}
|
||||||
|
<div className="border-t border-muted/20 pt-6 space-y-4">
|
||||||
|
<h3 className="text-sm font-semibold text-white flex items-center gap-2">
|
||||||
|
<Palette className="w-4 h-4 text-muted" /> Profile Color
|
||||||
|
</h3>
|
||||||
|
<div className="flex flex-wrap gap-3">
|
||||||
|
{MEMBER_COLOR_OPTIONS.map((colorClass) => {
|
||||||
|
const isSelected = selectedColor === colorClass;
|
||||||
|
return (
|
||||||
|
<button
|
||||||
|
key={colorClass}
|
||||||
|
type="button"
|
||||||
|
onClick={() => handleColorChange(colorClass)}
|
||||||
|
className={`w-8 h-8 rounded-full ${colorClass} transition-all flex items-center justify-center ${
|
||||||
|
isSelected
|
||||||
|
? "ring-2 ring-white ring-offset-2 ring-offset-surface scale-110"
|
||||||
|
: "hover:scale-105 opacity-80 hover:opacity-100 cursor-pointer"
|
||||||
|
}`}
|
||||||
|
aria-label={`Select ${colorClass}`}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue