add ability to setShareLinkExpiresAt value
This commit is contained in:
parent
cc4f2ad4ee
commit
ea33309b76
5 changed files with 69 additions and 50 deletions
|
|
@ -24,7 +24,7 @@ model Video {
|
|||
userId String
|
||||
sharing Boolean @default(false)
|
||||
delete_after_link_expires Boolean @default(false)
|
||||
shareExpiryAt DateTime?
|
||||
shareLinkExpiresAt DateTime?
|
||||
linkShareSeo Boolean @default(false)
|
||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,14 +1,51 @@
|
|||
import { Listbox, Transition } from "@headlessui/react";
|
||||
import { Fragment, useState } from "react";
|
||||
import { Fragment } from "react";
|
||||
import { getTime } from "~/utils/getTime";
|
||||
import { api } from "~/utils/api";
|
||||
|
||||
interface Props {
|
||||
shareExpiryAt: Date | null;
|
||||
shareLinkExpiresAt: Date | null;
|
||||
videoId: string;
|
||||
}
|
||||
|
||||
export default function ExpireDateSelectMenu({ shareExpiryAt }: Props) {
|
||||
const handleChange = (value) => {
|
||||
export default function ExpireDateSelectMenu({
|
||||
shareLinkExpiresAt,
|
||||
videoId,
|
||||
}: Props) {
|
||||
const utils = api.useContext();
|
||||
|
||||
const setShareLinkExpiresAtMutation =
|
||||
api.video.setShareLinkExpiresAt.useMutation({
|
||||
onMutate: async ({ videoId, shareLinkExpiresAt }) => {
|
||||
await utils.video.get.cancel();
|
||||
const previousValue = utils.video.get.getData({ videoId });
|
||||
if (previousValue) {
|
||||
utils.video.get.setData(
|
||||
{ videoId },
|
||||
{ ...previousValue, shareLinkExpiresAt }
|
||||
);
|
||||
}
|
||||
return { previousValue };
|
||||
},
|
||||
onError: (err, { videoId }, context) => {
|
||||
if (context?.previousValue) {
|
||||
utils.video.get.setData({ videoId }, context.previousValue);
|
||||
}
|
||||
console.error(err.message);
|
||||
},
|
||||
});
|
||||
const handleChange = (value: string) => {
|
||||
console.log("selecting value", value);
|
||||
|
||||
const now = new Date();
|
||||
now.setHours(now.getHours() + 1);
|
||||
|
||||
console.log(now);
|
||||
|
||||
setShareLinkExpiresAtMutation.mutate({
|
||||
videoId,
|
||||
shareLinkExpiresAt: now,
|
||||
});
|
||||
};
|
||||
|
||||
const availableExpireDates = [
|
||||
|
|
@ -21,12 +58,12 @@ export default function ExpireDateSelectMenu({ shareExpiryAt }: Props) {
|
|||
|
||||
return (
|
||||
<div>
|
||||
<Listbox value={shareExpiryAt} onChange={handleChange}>
|
||||
<Listbox value={shareLinkExpiresAt} onChange={handleChange}>
|
||||
<div>
|
||||
<Listbox.Button className="h-6 rounded border border-solid border-[#d5d9df] bg-white px-[7px] font-medium">
|
||||
<span className="block truncate">
|
||||
{typeof shareExpiryAt === null
|
||||
? getTime(shareExpiryAt)
|
||||
{shareLinkExpiresAt
|
||||
? getTime(shareLinkExpiresAt)
|
||||
: "Never expire"}
|
||||
</span>
|
||||
</Listbox.Button>
|
||||
|
|
|
|||
|
|
@ -129,7 +129,8 @@ export function ShareModal({ video }: Props) {
|
|||
<div className="flex h-6 items-center justify-between">
|
||||
<span>Expire link</span>
|
||||
<ExpireDateSelectMenu
|
||||
shareExpiryAt={video.shareExpiryAt}
|
||||
videoId={video.id}
|
||||
shareLinkExpiresAt={video.shareLinkExpiresAt}
|
||||
/>
|
||||
</div>
|
||||
<div className="mt-3 flex h-6 items-center justify-between">
|
||||
|
|
|
|||
|
|
@ -119,6 +119,28 @@ export const videoRouter = createTRPCRouter({
|
|||
throw new TRPCError({ code: "FORBIDDEN" });
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
updateVideo,
|
||||
};
|
||||
}),
|
||||
setShareLinkExpiresAt: protectedProcedure
|
||||
.input(z.object({ videoId: z.string(), shareLinkExpiresAt: z.date() }))
|
||||
.mutation(async ({ ctx, input }) => {
|
||||
const updateVideo = await ctx.prisma.video.updateMany({
|
||||
where: {
|
||||
id: input.videoId,
|
||||
userId: ctx.session.user.id,
|
||||
},
|
||||
data: {
|
||||
shareLinkExpiresAt: input.shareLinkExpiresAt,
|
||||
},
|
||||
});
|
||||
|
||||
if (updateVideo.count === 0) {
|
||||
throw new TRPCError({ code: "FORBIDDEN" });
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
updateVideo,
|
||||
|
|
|
|||
|
|
@ -1,41 +0,0 @@
|
|||
import { type RefCallback, useRef, useCallback, useMemo } from "react";
|
||||
import { createPopper, type Options } from "@popperjs/core";
|
||||
|
||||
/**
|
||||
* Example implementation to use Popper: https://popper.js.org/
|
||||
*/
|
||||
export function usePopper(
|
||||
options?: Partial<Options>
|
||||
): [RefCallback<Element | null>, RefCallback<HTMLElement | null>] {
|
||||
let reference = useRef<Element>(null);
|
||||
let popper = useRef<HTMLElement>(null);
|
||||
|
||||
let cleanupCallback = useRef(() => {});
|
||||
|
||||
let instantiatePopper = useCallback(() => {
|
||||
if (!reference.current) return;
|
||||
if (!popper.current) return;
|
||||
|
||||
if (cleanupCallback.current) cleanupCallback.current();
|
||||
|
||||
cleanupCallback.current = createPopper(
|
||||
reference.current,
|
||||
popper.current,
|
||||
options
|
||||
).destroy;
|
||||
}, [reference, popper, cleanupCallback, options]);
|
||||
|
||||
return useMemo(
|
||||
() => [
|
||||
(referenceDomNode) => {
|
||||
reference.current = referenceDomNode;
|
||||
instantiatePopper();
|
||||
},
|
||||
(popperDomNode) => {
|
||||
popper.current = popperDomNode;
|
||||
instantiatePopper();
|
||||
},
|
||||
],
|
||||
[reference, popper, instantiatePopper]
|
||||
);
|
||||
}
|
||||
Loading…
Reference in a new issue