feat(organization): add logo support for organizations

This commit is contained in:
Mauricio Siu
2025-02-25 23:28:19 -06:00
parent d3c59ff8af
commit 7d77e14319
4 changed files with 37 additions and 4 deletions

View File

@@ -35,14 +35,16 @@ export function AddOrganization({ organizationId }: Props) {
: api.organization.create.useMutation();
const [open, setOpen] = useState(false);
const [name, setName] = useState("");
const [logo, setLogo] = useState("");
useEffect(() => {
if (organization) {
setName(organization.name);
setLogo(organization.logo || "");
}
}, [organization]);
const handleSubmit = async () => {
await mutateAsync({ name, organizationId: organizationId ?? "" })
await mutateAsync({ name, logo, organizationId: organizationId ?? "" })
.then(() => {
setOpen(false);
toast.success(
@@ -91,7 +93,7 @@ export function AddOrganization({ organizationId }: Props) {
</DialogTitle>
<DialogDescription>
{organizationId
? "Update the organization name"
? "Update the organization name and logo"
: "Create a new organization to manage your projects."}
</DialogDescription>
</DialogHeader>
@@ -107,6 +109,18 @@ export function AddOrganization({ organizationId }: Props) {
className="col-span-3"
/>
</div>
<div className="grid grid-cols-4 items-center gap-4">
<Label htmlFor="logo" className="text-right">
Logo URL
</Label>
<Input
id="logo"
value={logo}
onChange={(e) => setLogo(e.target.value)}
placeholder="https://example.com/logo.png"
className="col-span-3"
/>
</div>
</div>
<DialogFooter>
<Button type="submit" onClick={handleSubmit} isLoading={isLoading}>

View File

@@ -562,6 +562,7 @@ function SidebarLogo() {
"transition-all",
state === "collapsed" ? "size-4" : "size-5",
)}
logoUrl={activeOrganization?.logo}
/>
</div>
<div
@@ -607,6 +608,7 @@ function SidebarLogo() {
"transition-all",
state === "collapsed" ? "size-6" : "size-10",
)}
logoUrl={org.logo ?? undefined}
/>
</div>
</DropdownMenuItem>

View File

@@ -1,8 +1,20 @@
interface Props {
className?: string;
logoUrl?: string;
}
export const Logo = ({ className = "size-14" }: Props) => {
export const Logo = ({ className = "size-14", logoUrl }: Props) => {
if (logoUrl) {
return (
<img
src={logoUrl}
alt="Organization Logo"
className={className}
style={{ objectFit: "contain" }}
/>
);
}
return (
<svg
xmlns="http://www.w3.org/2000/svg"

View File

@@ -11,6 +11,7 @@ export const organizationRouter = createTRPCRouter({
.input(
z.object({
name: z.string(),
logo: z.string().optional(),
}),
)
.mutation(async ({ ctx, input }) => {
@@ -81,6 +82,7 @@ export const organizationRouter = createTRPCRouter({
z.object({
organizationId: z.string(),
name: z.string(),
logo: z.string().optional(),
}),
)
.mutation(async ({ ctx, input }) => {
@@ -92,7 +94,10 @@ export const organizationRouter = createTRPCRouter({
}
const result = await db
.update(organization)
.set({ name: input.name })
.set({
name: input.name,
logo: input.logo,
})
.where(eq(organization.id, input.organizationId))
.returning();
return result[0];