Skip to content

Commit

Permalink
feat: ✨ Stream and chat features.
Browse files Browse the repository at this point in the history
- Create stream functionality.
- Implement chat feature.
- Create chat page.
- Create stream service.
- Create stream actions.
- Create loading skeletons for chat page.

Users can now define their chat settings.
  • Loading branch information
RicardoGEsteves committed Dec 15, 2023
1 parent d961e7c commit 7d21c91
Show file tree
Hide file tree
Showing 8 changed files with 242 additions and 0 deletions.
47 changes: 47 additions & 0 deletions actions/stream.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
"use server";

import { Stream } from "@prisma/client";
import { revalidatePath } from "next/cache";

import { db } from "@/lib/db";
import { getSelf } from "@/lib/auth-service";

export const updateStream = async (values: Partial<Stream>) => {
try {
const self = await getSelf();
const selfStream = await db.stream.findUnique({
where: {
userId: self.id,
},
});

if (!selfStream) {
throw new Error("Stream not found");
}

const validData = {
thumbnailUrl: values.thumbnailUrl,
name: values.name,
isChatEnabled: values.isChatEnabled,
isChatFollowersOnly: values.isChatFollowersOnly,
isChatDelayed: values.isChatDelayed,
};

const stream = await db.stream.update({
where: {
id: selfStream.id,
},
data: {
...validData,
},
});

revalidatePath(`/u/${self.username}/chat`);
revalidatePath(`/u/${self.username}`);
revalidatePath(`/${self.username}`);

return stream;
} catch {
throw new Error("Internal Error");
}
};
51 changes: 51 additions & 0 deletions app/(dashboard)/u/[username]/chat/_components/toggle-card.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
"use client";

import { toast } from "sonner";
import { useTransition } from "react";

import { Switch } from "@/components/ui/switch";
import { updateStream } from "@/actions/stream";
import { Skeleton } from "@/components/ui/skeleton";

type FieldTypes = "isChatEnabled" | "isChatDelayed" | "isChatFollowersOnly";

interface ToggleCardProps {
label: string;
value: boolean;
field: FieldTypes;
}

const ToggleCard = ({ label, value = false, field }: ToggleCardProps) => {
const [isPending, startTransition] = useTransition();

const onChange = () => {
startTransition(() => {
updateStream({ [field]: !value })
.then(() => toast.success("Chat settings updated!"))
.catch(() => toast.error("Something went wrong"));
});
};

return (
<div className="rounded-xl p-6 border">
<div className="flex items-center justify-between">
<p className="font-semibold shrink-0">{label}</p>
<div className="space-y-2">
<Switch
disabled={isPending}
onCheckedChange={onChange}
checked={value}
>
{value ? "On" : "Off"}
</Switch>
</div>
</div>
</div>
);
};

export default ToggleCard;

export const ToggleCardSkeleton = () => {
return <Skeleton className="rounded-xl p-10 w-full" />;
};
18 changes: 18 additions & 0 deletions app/(dashboard)/u/[username]/chat/loading.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { Skeleton } from "@/components/ui/skeleton";

import { ToggleCardSkeleton } from "./_components/toggle-card";

const ChatLoading = () => {
return (
<div className="p-6 space-y-4">
<Skeleton className="h-10 w-[200px]" />
<div className="space-y-4">
<ToggleCardSkeleton />
<ToggleCardSkeleton />
<ToggleCardSkeleton />
</div>
</div>
);
};

export default ChatLoading;
40 changes: 40 additions & 0 deletions app/(dashboard)/u/[username]/chat/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { getSelf } from "@/lib/auth-service";
import { getStreamByUserId } from "@/lib/stream-service";

import ToggleCard from "./_components/toggle-card";

const ChatPage = async () => {
const self = await getSelf();
const stream = await getStreamByUserId(self.id);

if (!stream) {
throw new Error("Stream not found");
}

return (
<div className="p-6">
<div className="mb-4">
<h1 className="text-2xl font-semibold">Settings</h1>
</div>
<div className="space-y-4">
<ToggleCard
field="isChatEnabled"
label="Enable chat"
value={stream.isChatEnabled}
/>
<ToggleCard
field="isChatDelayed"
label="Delay chat"
value={stream.isChatDelayed}
/>
<ToggleCard
field="isChatFollowersOnly"
label="Must be following to chat"
value={stream.isChatFollowersOnly}
/>
</div>
</div>
);
};

export default ChatPage;
29 changes: 29 additions & 0 deletions components/ui/switch.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
"use client"

import * as React from "react"
import * as SwitchPrimitives from "@radix-ui/react-switch"

import { cn } from "@/lib/utils"

const Switch = React.forwardRef<
React.ElementRef<typeof SwitchPrimitives.Root>,
React.ComponentPropsWithoutRef<typeof SwitchPrimitives.Root>
>(({ className, ...props }, ref) => (
<SwitchPrimitives.Root
className={cn(
"peer inline-flex h-6 w-11 shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=unchecked]:bg-input",
className
)}
{...props}
ref={ref}
>
<SwitchPrimitives.Thumb
className={cn(
"pointer-events-none block h-5 w-5 rounded-full bg-background shadow-lg ring-0 transition-transform data-[state=checked]:translate-x-5 data-[state=unchecked]:translate-x-0"
)}
/>
</SwitchPrimitives.Root>
))
Switch.displayName = SwitchPrimitives.Root.displayName

export { Switch }
9 changes: 9 additions & 0 deletions lib/stream-service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { db } from "@/lib/db";

export const getStreamByUserId = async (userId: string) => {
const stream = await db.stream.findUnique({
where: { userId },
});

return stream;
};
47 changes: 47 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"@prisma/client": "^5.7.0",
"@radix-ui/react-avatar": "^1.0.4",
"@radix-ui/react-slot": "^1.0.2",
"@radix-ui/react-switch": "^1.0.3",
"@radix-ui/react-tooltip": "^1.0.7",
"class-variance-authority": "^0.7.0",
"clsx": "^2.0.0",
Expand Down

0 comments on commit 7d21c91

Please sign in to comment.