Added the Ability to Update Board Background Images After Creation

This commit is contained in:
Ahmad 2024-04-30 20:01:22 -04:00
parent 4ddb7f99fd
commit ae6a8d69b8
No known key found for this signature in database
GPG key ID: 8FD8A93530D182BF
6 changed files with 123 additions and 6 deletions

View file

@ -16,7 +16,7 @@ Currently, there is no documentation or wiki available but, I do plan to add one
This will also be published on the site some time soon but for now, the roadmap will be listed here.
- [ ] Finish adding started at date feature
- [ ] Make board background image editable after board creation - _In Progress_
- [X] Make board background image editable after board creation
- [ ] Pagination for Audit Logs page
- [ ] Board sorting options (Boards Page)
- [ ] Add list and card views to boards page

View file

@ -16,10 +16,36 @@ const handler = async (data: InputType): Promise<ReturnType> => {
if (!userId || !orgId) return { error: 'Unauthorized' };
const { title, id } = data;
const { title, id, image } = data;
let board;
try {
const currentBoard = await db.board.findUnique({
where: {
id,
orgId,
},
select: {
imageId: true,
imageThumbUrl: true,
imageFullUrl: true,
imageUserName: true,
imageLinkHTML: true,
imageDownloadUrl: true,
},
});
const currentImageString = `${currentBoard?.imageId}|${currentBoard?.imageThumbUrl}|${currentBoard?.imageFullUrl}|${currentBoard?.imageUserName}|${currentBoard?.imageLinkHTML}|${currentBoard?.imageDownloadUrl}`;
const [
imageId,
imageThumbUrl,
imageFullUrl,
imageLinkHTML,
imageUserName,
imageDownloadUrl,
] = image?.split('|') || currentImageString.split('|');
board = await db.board.update({
where: {
id,
@ -27,6 +53,12 @@ const handler = async (data: InputType): Promise<ReturnType> => {
},
data: {
title,
imageId,
imageThumbUrl,
imageFullUrl,
imageLinkHTML,
imageUserName,
imageDownloadUrl,
},
});

View file

@ -8,6 +8,12 @@ export const UpdateBoard = z.object({
})
.min(3, {
message: 'Title must be at least 3 characters',
}),
})
.optional(),
id: z.string(),
image: z.optional(
z.string({
invalid_type_error: 'Image must be a string',
})
),
});

View file

@ -6,7 +6,6 @@ import { useLocalStorage } from 'usehooks-ts';
import { useOrganizationList, useOrganization } from '@clerk/nextjs';
import { Button } from '@/components/ui/button';
import { Separator } from '@/components/ui/separator';
import { Accordion } from '@/components/ui/accordion';
import { Skeleton } from '@/components/ui/skeleton';
import { NavItem, Organization } from './nav-item';

View file

@ -13,6 +13,7 @@ import {
PopoverTrigger,
} from '@/components/ui/popover';
import { copyBoard } from '@/actions/copy-board';
import { BoardUpdateImage } from './board-update-image';
interface BoardOptionsProps {
id: string;
@ -70,15 +71,16 @@ export const BoardOptions = ({ id }: BoardOptionsProps) => {
disabled={isLoadingCopy}
className='h-auto w-full justify-start rounded-none p-2 px-5 text-sm font-normal text-neutral-600'
>
Copy this board
Copy this Board
</Button>
<BoardUpdateImage boardId={id} />
<Button
variant='ghost'
onClick={onDelete}
disabled={isLoadingDelete}
className='h-auto w-full justify-start rounded-none p-2 px-5 text-sm font-normal text-destructive hover:text-destructive'
>
Delete this board
Delete this Board
</Button>
</PopoverContent>
</Popover>

View file

@ -0,0 +1,78 @@
import { X } from 'lucide-react';
import { toast } from 'sonner';
import { ElementRef, useRef } from 'react';
import Link from 'next/link';
import { Button } from '@/components/ui/button';
import {
Popover,
PopoverClose,
PopoverContent,
PopoverTrigger,
} from '@/components/ui/popover';
import { FormPicker } from '@/components/form/form-picker';
import { FormSubmit } from '@/components/form/form-submit';
import { useAction } from '@/hooks/use-action';
import { updateBoard } from '@/actions/update-board';
interface BoardUpdateImageProps {
boardId: string;
}
export const BoardUpdateImage = ({ boardId }: BoardUpdateImageProps) => {
const closeRef = useRef<ElementRef<'button'>>(null);
const { execute, fieldErrors } = useAction(updateBoard, {
onSuccess: (data) => {
toast.success('Board image updated');
closeRef.current?.click();
},
onError: (error) => {
toast.error(error);
},
});
const onSubmit = (formData: FormData) => {
const image = formData.get('image') as string;
execute({ id: boardId, image });
};
return (
<Popover>
<PopoverTrigger asChild>
<Button
variant='ghost'
className='h-auto w-full justify-start p-2 px-5 text-sm font-normal text-neutral-600'
>
Change Background Image
</Button>
</PopoverTrigger>
<PopoverContent className='w-80 pt-3' side='left' align='start'>
<PopoverClose asChild>
<Button
className='absolute right-2 top-2 h-auto w-auto p-2 text-neutral-600'
variant='ghost'
>
<X className='h-4 w-4' />
</Button>
</PopoverClose>
<form action={onSubmit} className='space-y-4'>
<div className='space-y-4'>
<p className='text-center text-xs font-medium italic text-neutral-700'>
Images Provided by{' '}
<Link
className='text-sky-900 underline'
href='https://unsplash.com/'
>
Unsplash
</Link>
</p>
<FormPicker id='image' errors={fieldErrors} />
</div>
<FormSubmit className='w-full'>Update</FormSubmit>
</form>
</PopoverContent>
</Popover>
);
};