feat(guide): proper order sorting & hidden
This commit is contained in:
@@ -23,6 +23,7 @@ import { guides } from "@/lib/db/schema";
|
|||||||
export default async function GuideEditPage({
|
export default async function GuideEditPage({
|
||||||
params,
|
params,
|
||||||
}: PageProps<"/admin/guide/[id]">) {
|
}: PageProps<"/admin/guide/[id]">) {
|
||||||
|
if (!(await adminCheck())) redirect("/login");
|
||||||
const { id } = await params;
|
const { id } = await params;
|
||||||
const [guide] = await db.select().from(guides).where(eq(guides.id, id));
|
const [guide] = await db.select().from(guides).where(eq(guides.id, id));
|
||||||
if (!guide) notFound();
|
if (!guide) notFound();
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import { db } from "@/lib/db";
|
|||||||
import { guides } from "@/lib/db/schema";
|
import { guides } from "@/lib/db/schema";
|
||||||
|
|
||||||
export default async function GuideCreatePage() {
|
export default async function GuideCreatePage() {
|
||||||
|
if (!(await adminCheck())) redirect("/login");
|
||||||
const [{ maxOrder }] = await db
|
const [{ maxOrder }] = await db
|
||||||
.select({
|
.select({
|
||||||
maxOrder: sql<number>`
|
maxOrder: sql<number>`
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
"use server";
|
||||||
|
|
||||||
|
import { eq, not } from "drizzle-orm";
|
||||||
|
import { revalidatePath } from "next/cache";
|
||||||
|
import { redirect } from "next/navigation";
|
||||||
|
import { adminCheck } from "@/lib/auth";
|
||||||
|
import { db } from "@/lib/db";
|
||||||
|
import { guides } from "@/lib/db/schema";
|
||||||
|
|
||||||
|
export async function hideGuide(id: string) {
|
||||||
|
if (!(await adminCheck())) redirect("/login");
|
||||||
|
await db
|
||||||
|
.update(guides)
|
||||||
|
.set({
|
||||||
|
hidden: not(guides.hidden),
|
||||||
|
})
|
||||||
|
.where(eq(guides.id, id));
|
||||||
|
revalidatePath("/admin/guide");
|
||||||
|
}
|
||||||
@@ -1,12 +1,14 @@
|
|||||||
import { Pencil, PlusIcon } from "lucide-react";
|
import { EyeIcon, EyeOffIcon, Pencil, PlusIcon } from "lucide-react";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import Image from "@/components/image";
|
import Image from "@/components/image";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { Card, CardHeader, CardTitle } from "@/components/ui/card";
|
import { Card, CardHeader, CardTitle } from "@/components/ui/card";
|
||||||
|
import { cn } from "@/lib/utils";
|
||||||
import { searchGuide } from "../../guide/api";
|
import { searchGuide } from "../../guide/api";
|
||||||
|
import { hideGuide } from "./api";
|
||||||
|
|
||||||
export default async function AdminGuidePage() {
|
export default async function AdminGuidePage() {
|
||||||
const list = await searchGuide();
|
const list = await searchGuide("", true);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="grow-0 flex flex-col pt-5 gap-2 mx-4">
|
<div className="grow-0 flex flex-col pt-5 gap-2 mx-4">
|
||||||
@@ -20,18 +22,25 @@ export default async function AdminGuidePage() {
|
|||||||
{list.map((card) => (
|
{list.map((card) => (
|
||||||
<Card
|
<Card
|
||||||
key={card.id}
|
key={card.id}
|
||||||
className="bg-card/50 hover:bg-border backdrop-blur-sm transition-colors py-3 sm:py-6 rounded-sm sm:rounded-xl group relative"
|
className={cn(
|
||||||
|
"bg-card/50 hover:bg-border backdrop-blur-sm transition-colors py-3 sm:py-6 rounded-sm sm:rounded-xl group relative",
|
||||||
|
card.hidden && "opacity-70",
|
||||||
|
)}
|
||||||
>
|
>
|
||||||
|
<div className="flex gap-1 absolute opacity-0 group-hover:opacity-100 transition-opacity top-0 right-0 m-2">
|
||||||
<Button
|
<Button
|
||||||
size="icon"
|
size="icon"
|
||||||
variant="outline"
|
variant="outline"
|
||||||
className="absolute opacity-0 group-hover:opacity-100 transition-opacity top-0 right-0 m-2"
|
onClick={hideGuide.bind(null, card.id)}
|
||||||
asChild
|
|
||||||
>
|
>
|
||||||
|
{card.hidden ? <EyeOffIcon /> : <EyeIcon />}
|
||||||
|
</Button>
|
||||||
|
<Button size="icon" variant="outline" asChild>
|
||||||
<Link href={`/admin/guide/${card.id}`}>
|
<Link href={`/admin/guide/${card.id}`}>
|
||||||
<Pencil />
|
<Pencil />
|
||||||
</Link>
|
</Link>
|
||||||
</Button>
|
</Button>
|
||||||
|
</div>
|
||||||
<CardHeader className="px-3 sm:px-6">
|
<CardHeader className="px-3 sm:px-6">
|
||||||
<CardTitle>{card.name}</CardTitle>
|
<CardTitle>{card.name}</CardTitle>
|
||||||
<div className="relative w-full aspect-square mt-2 rounded-sm sm:rounded-lg border overflow-hidden">
|
<div className="relative w-full aspect-square mt-2 rounded-sm sm:rounded-lg border overflow-hidden">
|
||||||
|
|||||||
@@ -1,13 +1,18 @@
|
|||||||
"use server";
|
"use server";
|
||||||
|
|
||||||
import { ilike } from "drizzle-orm";
|
import { and, desc, ilike, not } from "drizzle-orm";
|
||||||
import { db } from "@/lib/db";
|
import { db } from "@/lib/db";
|
||||||
import { guides } from "@/lib/db/schema";
|
import { guides } from "@/lib/db/schema";
|
||||||
|
|
||||||
export async function searchGuide(search: string = "") {
|
export async function searchGuide(search: string = "", admin = false) {
|
||||||
return await db
|
return await db
|
||||||
.select()
|
.select()
|
||||||
.from(guides)
|
.from(guides)
|
||||||
.where(ilike(guides.name, `%${search}%`))
|
.where(
|
||||||
.orderBy(guides.id);
|
and(
|
||||||
|
ilike(guides.name, `%${search}%`),
|
||||||
|
admin ? undefined : not(guides.hidden),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.orderBy(desc(guides.order));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,6 @@ import { searchGuide } from "./api";
|
|||||||
import { GuideList } from "./client";
|
import { GuideList } from "./client";
|
||||||
|
|
||||||
export default async function GuidePage() {
|
export default async function GuidePage() {
|
||||||
const initialData = await searchGuide();
|
const initialData = await searchGuide("");
|
||||||
return <GuideList initialList={initialData} />;
|
return <GuideList initialList={initialData} />;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user