Skip to content

Commit

Permalink
feat: Redesign /browse (#317)
Browse files Browse the repository at this point in the history
  • Loading branch information
evadecker authored Dec 28, 2024
1 parent d362596 commit 189df29
Show file tree
Hide file tree
Showing 19 changed files with 407 additions and 253 deletions.
5 changes: 5 additions & 0 deletions .changeset/olive-wasps-smile.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"namesake": minor
---

Improve design of browse page and allow previewing quests before addition
9 changes: 7 additions & 2 deletions convex/quests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,13 @@ import { DEFAULT_TIME_REQUIRED } from "./constants";
import { userMutation } from "./helpers";
import { category, jurisdiction, timeRequiredUnit } from "./validators";

// TODO: Add `returns` value validation
// https://docs.convex.dev/functions/validation
export const count = query({
args: {},
handler: async (ctx) => {
const quests = await ctx.db.query("quests").collect();
return quests.length;
},
});

export const getAll = query({
args: {},
Expand Down
3 changes: 0 additions & 3 deletions convex/userQuests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,6 @@ import { type Category, STATUS, type Status } from "./constants";
import { userMutation, userQuery } from "./helpers";
import { status } from "./validators";

// TODO: Add `returns` value validation
// https://docs.convex.dev/functions/validation

export const getAll = userQuery({
args: {},
handler: async (ctx, _args) => {
Expand Down
3 changes: 0 additions & 3 deletions convex/users.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,6 @@ import { DUPLICATE_EMAIL, INVALID_EMAIL } from "./errors";
import { userMutation, userQuery } from "./helpers";
import { jurisdiction } from "./validators";

// TODO: Add `returns` value validation
// https://docs.convex.dev/functions/validation

export const getAll = query({
args: {},
handler: async (ctx) => {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import { Button, Link } from "@/components/common";
import { api } from "@convex/_generated/api";
import type { Doc } from "@convex/_generated/dataModel";
import { useMutation, useQuery } from "convex/react";
import { ArrowRight, LoaderCircle, Plus } from "lucide-react";
import { useState } from "react";
import { toast } from "sonner";

interface AddOrGoToQuestButtonProps {
quest: Doc<"quests">;
size?: "small" | "medium";
className?: string;
}

export function AddOrGoToQuestButton({
quest,
size = "medium",
className,
}: AddOrGoToQuestButtonProps) {
const [isAdding, setIsAdding] = useState(false);
const addQuest = useMutation(api.userQuests.create);
const userQuest = useQuery(api.userQuests.getByQuestId, {
questId: quest._id,
});

if (quest === undefined) return null;
if (quest === null) return null;

const handleAddQuest = () => {
setIsAdding(true);
addQuest({ questId: quest._id })
.then(() => {
toast.success(`Added ${quest.title} quest`);
})
.then(() => setIsAdding(false));
};

if (userQuest === undefined) return null;

if (!userQuest) {
return (
<Button
onPress={handleAddQuest}
isDisabled={isAdding}
aria-label={isAdding ? "Adding" : "Add quest"}
size={size}
variant={size === "small" ? "secondary" : "primary"}
className={className}
>
{isAdding ? (
<LoaderCircle size={16} className="animate-spin" />
) : (
<Plus size={16} />
)}
Add
</Button>
);
}

return (
<Link
href={{ to: "/quests/$questId", params: { questId: quest._id } }}
button={{ variant: "secondary", size }}
aria-label="Go to quest"
className={className}
>
{size === "small" ? <ArrowRight size={16} /> : "Go to quest"}
</Link>
);
}
1 change: 1 addition & 0 deletions src/components/browse/AddOrGoToQuestButton/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./AddOrGoToQuestButton";
1 change: 1 addition & 0 deletions src/components/browse/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./AddOrGoToQuestButton";
9 changes: 8 additions & 1 deletion src/components/common/Nav/Nav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -77,12 +77,19 @@ interface NavGroupProps {
label: string;
children: React.ReactNode;
count?: number;
icon?: LucideIcon;
}

export const NavGroup = ({ label, children, count }: NavGroupProps) => {
export const NavGroup = ({
label,
children,
count,
icon: Icon,
}: NavGroupProps) => {
return (
<div className="flex flex-col gap-0.5 [&:not(:first-child)]:mt-4">
<Header className="text-sm h-8 font-medium text-gray-dim border-b border-gray-4 dark:border-graydark-4 flex justify-start items-center gap-1.5">
{Icon && <Icon size={20} className="size-4" />}
{label}
{count && (
<Badge size="xs" className="rounded-full">
Expand Down
31 changes: 31 additions & 0 deletions src/components/quests/QuestPageHeader/QuestPageHeader.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { PageHeader, type PageHeaderProps } from "@/components/app";
import { Badge } from "@/components/common";
import type { Doc } from "@convex/_generated/dataModel";

interface QuestPageHeaderProps extends Omit<PageHeaderProps, "title"> {
quest?: Doc<"quests"> | null;
}

export function QuestPageHeader({
quest,
badge,
icon: Icon,
children,
className,
}: QuestPageHeaderProps) {
return (
<PageHeader
title={quest === null ? "Unknown" : (quest?.title ?? "")}
icon={Icon}
badge={
<>
{quest?.jurisdiction && <Badge>{quest.jurisdiction}</Badge>}
{badge}
</>
}
className={className}
>
{children}
</PageHeader>
);
}
1 change: 1 addition & 0 deletions src/components/quests/QuestPageHeader/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./QuestPageHeader";
1 change: 1 addition & 0 deletions src/components/quests/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export * from "./QuestCosts";
export * from "./QuestDetails";
export * from "./QuestDocuments";
export * from "./QuestForm";
export * from "./QuestPageHeader";
export * from "./QuestTimeRequired";
export * from "./QuestUrls";
export * from "./QuestUsageCount";
Expand Down
Loading

0 comments on commit 189df29

Please sign in to comment.