mirror of
https://github.com/lukevella/rallly.git
synced 2025-06-02 18:51:52 +02:00
💄 Update poll page (#1672)
This commit is contained in:
parent
12651abd0c
commit
cf90e7a6df
9 changed files with 95 additions and 55 deletions
|
@ -1,6 +1,6 @@
|
||||||
import type { PollStatus } from "@rallly/database";
|
import type { PollStatus } from "@rallly/database";
|
||||||
import { Button } from "@rallly/ui/button";
|
import { Button } from "@rallly/ui/button";
|
||||||
import { shortUrl } from "@rallly/utils/absolute-url";
|
import { absoluteUrl, shortUrl } from "@rallly/utils/absolute-url";
|
||||||
import { InboxIcon } from "lucide-react";
|
import { InboxIcon } from "lucide-react";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
|
@ -186,6 +186,7 @@ export default async function Page({
|
||||||
title={poll.title}
|
title={poll.title}
|
||||||
status={poll.status}
|
status={poll.status}
|
||||||
participants={poll.participants}
|
participants={poll.participants}
|
||||||
|
pollLink={absoluteUrl(`/poll/${poll.id}`)}
|
||||||
inviteLink={shortUrl(`/invite/${poll.id}`)}
|
inviteLink={shortUrl(`/invite/${poll.id}`)}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
|
|
|
@ -54,10 +54,11 @@ export function InvitePage() {
|
||||||
const poll = usePoll();
|
const poll = usePoll();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="mx-auto max-w-4xl space-y-3 p-3 lg:space-y-4 lg:px-4 lg:py-8">
|
<div>
|
||||||
{/* Track poll views */}
|
|
||||||
<PollViewTracker pollId={poll.id} />
|
<PollViewTracker pollId={poll.id} />
|
||||||
<PollHeader />
|
<PollHeader />
|
||||||
|
<div className="p-3">
|
||||||
|
<div className="mx-auto w-full max-w-4xl space-y-4">
|
||||||
<GoToApp />
|
<GoToApp />
|
||||||
<EventCard />
|
<EventCard />
|
||||||
<ScheduledEvent />
|
<ScheduledEvent />
|
||||||
|
@ -67,5 +68,7 @@ export function InvitePage() {
|
||||||
<Discussion />
|
<Discussion />
|
||||||
<PollFooter />
|
<PollFooter />
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
import Discussion from "@/components/discussion";
|
import Discussion from "@/components/discussion";
|
||||||
import { EventCard } from "@/components/event-card";
|
import { EventCard } from "@/components/event-card";
|
||||||
import { PollFooter } from "@/components/poll/poll-footer";
|
import { PollFooter } from "@/components/poll/poll-footer";
|
||||||
import { PollHeader } from "@/components/poll/poll-header";
|
|
||||||
import { PollViewTracker } from "@/components/poll/poll-view-tracker";
|
import { PollViewTracker } from "@/components/poll/poll-view-tracker";
|
||||||
import { ResponsiveResults } from "@/components/poll/responsive-results";
|
import { ResponsiveResults } from "@/components/poll/responsive-results";
|
||||||
import { ScheduledEvent } from "@/components/poll/scheduled-event";
|
import { ScheduledEvent } from "@/components/poll/scheduled-event";
|
||||||
|
@ -21,7 +20,6 @@ export function AdminPage() {
|
||||||
{/* Track poll views */}
|
{/* Track poll views */}
|
||||||
<PollViewTracker pollId={poll.id} />
|
<PollViewTracker pollId={poll.id} />
|
||||||
<UnsubscribeAlert />
|
<UnsubscribeAlert />
|
||||||
<PollHeader />
|
|
||||||
<GuestPollAlert />
|
<GuestPollAlert />
|
||||||
<EventCard />
|
<EventCard />
|
||||||
<ScheduledEvent />
|
<ScheduledEvent />
|
||||||
|
|
|
@ -7,14 +7,12 @@ import {
|
||||||
LogInIcon,
|
LogInIcon,
|
||||||
LogOutIcon,
|
LogOutIcon,
|
||||||
ShieldCloseIcon,
|
ShieldCloseIcon,
|
||||||
XIcon,
|
|
||||||
} from "lucide-react";
|
} from "lucide-react";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { useParams, usePathname } from "next/navigation";
|
import { useParams, usePathname } from "next/navigation";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
|
||||||
import { LogoutButton } from "@/app/components/logout-button";
|
import { LogoutButton } from "@/app/components/logout-button";
|
||||||
import { PollPageIcon } from "@/app/components/page-icons";
|
|
||||||
import { InviteDialog } from "@/components/invite-dialog";
|
import { InviteDialog } from "@/components/invite-dialog";
|
||||||
import { LoginLink } from "@/components/login-link";
|
import { LoginLink } from "@/components/login-link";
|
||||||
import {
|
import {
|
||||||
|
@ -46,15 +44,19 @@ const Layout = ({ children }: React.PropsWithChildren) => {
|
||||||
const pollLink = `/poll/${poll.id}`;
|
const pollLink = `/poll/${poll.id}`;
|
||||||
const pathname = usePathname();
|
const pathname = usePathname();
|
||||||
return (
|
return (
|
||||||
<div className="bg-gray-100">
|
<div>
|
||||||
<div className="sticky top-0 z-30 flex flex-col justify-between gap-x-4 gap-y-2.5 border-b bg-gray-100 p-3 sm:flex-row lg:items-center lg:px-5">
|
<div className="sticky top-0 z-30 border-b bg-gray-100/90 p-3 backdrop-blur-md sm:flex-row">
|
||||||
|
<div className="mx-auto flex max-w-4xl justify-between">
|
||||||
<div className="flex min-w-0 items-center gap-x-2.5">
|
<div className="flex min-w-0 items-center gap-x-2.5">
|
||||||
{pathname === pollLink ? (
|
{pathname === pollLink ? (
|
||||||
<Button variant="ghost" asChild>
|
<Button variant="ghost" asChild>
|
||||||
<Link href="/polls">
|
<Link href="/polls">
|
||||||
<Icon>
|
<Icon>
|
||||||
<XIcon />
|
<ArrowLeftIcon />
|
||||||
</Icon>
|
</Icon>
|
||||||
|
<span>
|
||||||
|
<Trans i18nKey="back" defaults="Back" />
|
||||||
|
</span>
|
||||||
</Link>
|
</Link>
|
||||||
</Button>
|
</Button>
|
||||||
) : (
|
) : (
|
||||||
|
@ -63,20 +65,20 @@ const Layout = ({ children }: React.PropsWithChildren) => {
|
||||||
<Icon>
|
<Icon>
|
||||||
<ArrowLeftIcon />
|
<ArrowLeftIcon />
|
||||||
</Icon>
|
</Icon>
|
||||||
|
<span>
|
||||||
|
<Trans i18nKey="back" defaults="Back" />
|
||||||
|
</span>
|
||||||
</Link>
|
</Link>
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
<div>
|
|
||||||
<PollPageIcon size="sm" />
|
|
||||||
</div>
|
|
||||||
<h1 className="truncate text-sm font-semibold">{poll.title}</h1>
|
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<AdminControls />
|
<AdminControls />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="mx-auto max-w-4xl space-y-3 p-3 lg:space-y-4 lg:px-4 lg:py-8">
|
</div>
|
||||||
{children}
|
<div className="p-3">
|
||||||
|
<div className="mx-auto max-w-4xl space-y-3">{children}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -151,11 +151,13 @@ const ManagePoll: React.FunctionComponent<{
|
||||||
<>
|
<>
|
||||||
<DropdownMenu modal={false}>
|
<DropdownMenu modal={false}>
|
||||||
<DropdownMenuTrigger asChild={true}>
|
<DropdownMenuTrigger asChild={true}>
|
||||||
<Button disabled={disabled}>
|
<Button variant="ghost" disabled={disabled}>
|
||||||
<Icon>
|
<Icon>
|
||||||
<SettingsIcon />
|
<SettingsIcon />
|
||||||
</Icon>
|
</Icon>
|
||||||
|
<span className="hidden sm:block">
|
||||||
<Trans i18nKey="manage" />
|
<Trans i18nKey="manage" />
|
||||||
|
</span>
|
||||||
<Icon>
|
<Icon>
|
||||||
<ChevronDownIcon />
|
<ChevronDownIcon />
|
||||||
</Icon>
|
</Icon>
|
||||||
|
|
|
@ -83,7 +83,7 @@ const NotificationsToggle: React.FunctionComponent = () => {
|
||||||
<Button
|
<Button
|
||||||
data-testid="notifications-toggle"
|
data-testid="notifications-toggle"
|
||||||
disabled={user.isGuest}
|
disabled={user.isGuest}
|
||||||
className="flex items-center gap-2 px-2.5"
|
variant="ghost"
|
||||||
onClick={async () => {
|
onClick={async () => {
|
||||||
if (user.isGuest) {
|
if (user.isGuest) {
|
||||||
signIn();
|
signIn();
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { Trans } from "@/components/trans";
|
||||||
|
|
||||||
export function PollFooter() {
|
export function PollFooter() {
|
||||||
return (
|
return (
|
||||||
<div className="py-4 text-center text-sm text-gray-500">
|
<div className="pb-12 pt-4 text-center text-sm text-gray-500">
|
||||||
<Trans
|
<Trans
|
||||||
defaults="Powered by <a>{name}</a>"
|
defaults="Powered by <a>{name}</a>"
|
||||||
i18nKey="poweredByRallly"
|
i18nKey="poweredByRallly"
|
||||||
|
|
|
@ -1,14 +1,46 @@
|
||||||
import { LogoLink } from "@/app/components/logo-link";
|
import { Button } from "@rallly/ui/button";
|
||||||
|
import Image from "next/image";
|
||||||
|
import Link from "next/link";
|
||||||
|
|
||||||
import { UserDropdown } from "@/components/user-dropdown";
|
import { UserDropdown } from "@/components/user-dropdown";
|
||||||
|
|
||||||
|
import { useUser } from "../user-provider";
|
||||||
|
|
||||||
export function PollHeader() {
|
export function PollHeader() {
|
||||||
|
const { user } = useUser();
|
||||||
return (
|
return (
|
||||||
<div className="flex items-center justify-between">
|
<div className="sticky top-0 z-30 border-b bg-gray-100/90 p-3 backdrop-blur-md">
|
||||||
|
<div className="mx-auto flex max-w-4xl items-center justify-between">
|
||||||
<div className="flex items-center gap-x-2.5">
|
<div className="flex items-center gap-x-2.5">
|
||||||
<LogoLink />
|
<Link
|
||||||
|
className="transition-transform active:translate-y-1"
|
||||||
|
href="https://rallly.co"
|
||||||
|
>
|
||||||
|
<Image
|
||||||
|
src="/images/logo-mark.svg"
|
||||||
|
alt="Rallly"
|
||||||
|
width={32}
|
||||||
|
height={32}
|
||||||
|
priority={true}
|
||||||
|
className="shrink-0"
|
||||||
|
/>
|
||||||
|
<span className="sr-only">Rallly</span>
|
||||||
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center gap-x-2.5">
|
<div className="flex items-center gap-x-2.5">
|
||||||
|
{user.email ? (
|
||||||
<UserDropdown />
|
<UserDropdown />
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<Button variant="ghost" asChild>
|
||||||
|
<Link href="/login">Login</Link>
|
||||||
|
</Button>
|
||||||
|
<Button variant="primary" asChild>
|
||||||
|
<Link href="/register">Sign Up</Link>
|
||||||
|
</Button>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -14,11 +14,13 @@ export function PollListItem({
|
||||||
status,
|
status,
|
||||||
participants,
|
participants,
|
||||||
inviteLink,
|
inviteLink,
|
||||||
|
pollLink,
|
||||||
}: {
|
}: {
|
||||||
title: string;
|
title: string;
|
||||||
status: PollStatus;
|
status: PollStatus;
|
||||||
participants: { id: string; name: string; image?: string }[];
|
participants: { id: string; name: string; image?: string }[];
|
||||||
inviteLink: string;
|
inviteLink: string;
|
||||||
|
pollLink: string;
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<StackedListItem>
|
<StackedListItem>
|
||||||
|
@ -26,7 +28,7 @@ export function PollListItem({
|
||||||
<PollStatusIcon status={status} showTooltip={false} />
|
<PollStatusIcon status={status} showTooltip={false} />
|
||||||
<Link
|
<Link
|
||||||
className="focus:ring-ring min-w-0 text-sm font-medium hover:underline focus-visible:ring-2"
|
className="focus:ring-ring min-w-0 text-sm font-medium hover:underline focus-visible:ring-2"
|
||||||
href={inviteLink}
|
href={pollLink}
|
||||||
>
|
>
|
||||||
<span className="absolute inset-0" />
|
<span className="absolute inset-0" />
|
||||||
<span className="block truncate">{title}</span>
|
<span className="block truncate">{title}</span>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue