before react 19 upgrade

This commit is contained in:
2025-02-04 14:13:01 -05:00
parent a2f6aef11a
commit 79ed00b7c0
13 changed files with 240 additions and 443 deletions

View File

@@ -1,44 +1,49 @@
"use server";
import { eq, not , asc} from "drizzle-orm";
import { eq, asc} from "drizzle-orm";
import { revalidatePath } from "next/cache";
import { db } from "@db/index";
import { accounts } from "@schemas/schema";
import { vw_accounts } from "@schemas/schema";
import { users } from "@schemas/schema";
export const getData = async () => {
const data = await db.select().from(accounts).orderBy(asc(accounts.userId));
export const getAllUsers = async () => {
const data = await db.select().from(users).orderBy(asc(users.email));
return data;
};
export const getAllAccounts = async () => {
return getData();
return getAllUsers();
};
export const getViewAccounts = async () => {
const data = await db.select().from(vw_accounts).orderBy(asc(vw_accounts.last_name));
return data;
export const getUser = async (userId : string) => {
const data = await db.select().from(users).where(eq(users.id, userId));
return data[0];
};
export const addAccount = async ( first_name: string, last_name: string, username: string, email: string, password_hash : string) => {
/* await db.insert(accounts).values({
first_name : first_name, last_name: last_name, username: username, password_hash : password_hash
}); */
export const addUser = async ( first_name: string, last_name: string, username: string, email: string, hashedPassword : string) => {
await db.insert(users).values({
id: crypto.randomUUID(),
first_name: first_name,
last_name: last_name,
username: username,
hashedPassword: hashedPassword,
email: email
});
};
export const deleteAccount = async (id: number) => {
await db.delete(accounts).where(eq(accounts.userId, id));
export const deleteUser = async (id: string) => {
await db.delete(users).where(eq(users.id, id));
revalidatePath("/");
};
export const editAccount = async (id: number, first_name: string, last_name: string, username: string, email : string, password_hash: string) => {
export const editUser = async (id: string, first_name: string, last_name: string, username: string, email : string, hashedPassword: string) => {
await db
.update(accounts)
.update(users)
.set({
first_name : first_name,
last_name: last_name,
username: username,
email: email,
password_hash: password_hash
hashedPassword: hashedPassword
})
.where(eq(accounts.userId, id));
.where(eq(users.id, id));
revalidatePath("/");
};

View File

@@ -18,7 +18,6 @@ export default async function AccountsPage() {
return (
<div>
<PageHero title="Accounts" />
<div className="container mx-auto">
<Suspense fallback="Loading...">
<AccountsTable data={data} newColumnHeadings={columnHeadings}></AccountsTable>

View File

@@ -1,14 +1,17 @@
import { users } from "@schemas/schema";
import { getData } from "@actions/accountActions";
import UserForm from "@components/Account/UserForm";
import { getUser } from "@/actions/accountActions";
import { validateRequest } from "@/lib/wdcStarter/auth";
export default async function MyAccountsPage() {
const data = await getData();
const {session, user} = await validateRequest();
const theUser = session?.userId ? await getUser(session.userId.toString()) : null;
return (
<div className="bg-gray-100 min-h-screen flex flex-col">
<div>
My account Page
</div>
{/* <Account account={data} /> */}
<UserForm user={user} />
</div>
);
}

View File

@@ -0,0 +1,92 @@
'use client';
import React, { useState, ChangeEvent, FormEvent } from "react";
import {users} from "@schemas/schema"
interface User {
id: string;
name: string;
email: string;
emailVerified: string | null;
image: string | null;
}
interface UserFormProps {
user: typeof users;
onSave: (user: typeof users) => void;
onCancel: () => void;
}
const UserForm: React.FC<UserFormProps> = ({ user, onSave, onCancel }) => {
const [formData, setFormData] = useState<typeof users>(user);
const handleChange = (e: ChangeEvent<HTMLInputElement>) => {
const { name, value } = e.target;
setFormData({ ...formData, [name]: value });
};
const handleSubmit = (e: FormEvent) => {
e.preventDefault();
onSave(formData);
};
return (
<form onSubmit={handleSubmit} className="space-y-4">
<div>
<label htmlFor="email" className="block text-sm font-medium text-gray-700">
Email
</label>
<input
type="email"
name="email"
id="email"
value={formData.email}
onChange={handleChange}
className="mt-1 block w-full border border-gray-300 rounded-md shadow-sm"
/>
</div>
<div>
<label htmlFor="emailVerified" className="block text-sm font-medium text-gray-700">
Email Verified
</label>
<input
type="datetime-local"
name="emailVerified"
id="emailVerified"
value={formData.emailVerified || ""}
onChange={handleChange}
className="mt-1 block w-full border border-gray-300 rounded-md shadow-sm"
/>
</div>
<div>
<label htmlFor="image" className="block text-sm font-medium text-gray-700">
Image
</label>
<input
type="text"
name="image"
id="image"
value={formData.image || ""}
onChange={handleChange}
className="mt-1 block w-full border border-gray-300 rounded-md shadow-sm"
/>
</div>
<div className="flex justify-end space-x-4">
<button
type="button"
onClick={onCancel}
className="px-4 py-2 bg-gray-300 text-gray-700 rounded-md"
>
Cancel
</button>
<button
type="submit"
className="px-4 py-2 bg-blue-600 text-white rounded-md"
>
Save
</button>
</div>
</form>
);
};
export default UserForm;

View File

@@ -154,11 +154,7 @@ export default function PopNavDialog(props:any) {
<div className="grid grid-cols-2 gap-x-4">
{category.featured.map((item) => (
<div key={item.name} className="group relative text-sm">
<img
alt={item.imageAlt}
src={item.imageSrc}
className="aspect-square w-full rounded-lg bg-gray-100 object-cover group-hover:opacity-75"
/>
<img alt={item.imageAlt} src={item.imageSrc} className="aspect-square w-full rounded-lg bg-gray-100 object-cover group-hover:opacity-75"/>
<a
href={item.href}
className="mt-6 block font-medium text-gray-900"
@@ -377,7 +373,7 @@ export default function PopNavDialog(props:any) {
<div className="ml-auto flex items-center">
<div className="hidden lg:flex lg:flex-1 lg:items-center lg:justify-end lg:space-x-6">
<a
href={linkPath} onClick={async (e) => {e.preventDefault; console.log("in the onclick"); await logout()} } className="text-sm font-medium text-gray-700 hover:text-gray-800">
href={linkPath} onClick={async (e) => {e.preventDefault(); console.log("in the onclick"); await logout()} } className="text-sm font-medium text-gray-700 hover:text-gray-800">
{user == null?"Sign In": "Log Out"}
</a>
<span aria-hidden="true" className="h-6 w-px bg-gray-200" />

View File

@@ -21,7 +21,7 @@ export default function RootLayout(props: { children: React.ReactNode }) {
const { children } = props;
return (
/* <ClerkProvider> */
<html lang="en" suppressHydrationWarning className={""}>
<body className="bg-slate-200 ">
<header>
@@ -40,6 +40,6 @@ export default function RootLayout(props: { children: React.ReactNode }) {
<Footer />
</body>
</html>
/* </ClerkProvider> */
)
}

View File

@@ -17,6 +17,7 @@ export default async function AccountsTable( props: any ) {
<div className="mt-8 flow-root">
<div className="-mx-4 -my-2 overflow-x-auto sm:-mx-6 lg:-mx-8">
<div className="inline-block min-w-full py-2 align-middle sm:px-6 lg:px-8">
<Suspense fallback={<Loading />}>
<table className="min-w-full divide-y divide-gray-300">
<thead>
<tr>
@@ -66,7 +67,7 @@ export default async function AccountsTable( props: any ) {
</tr>
</thead>
<tbody className=" divide-y divide-gray-200 bg-white">
<Suspense fallback={<Loading />}>
{props.data.map((item: any) => (
<tr key={item.uuid}>
<td className="whitespace-wrap flex items-center py-4 pl-4 pr-3 text-xs font-medium text-gray-900 ">
@@ -97,10 +98,10 @@ export default async function AccountsTable( props: any ) {
</td>
</tr>
))}
</Suspense>
</tbody>
</table>
</Suspense>
</div>
</div>
</div>

0
src/components/Aco Normal file
View File

View File

@@ -5,40 +5,40 @@ import { isAdmin } from "@/actions/userActions";
const navigation = {
armory: [
{ name: 'Builder', href: '/Builder', role: null },
{ name: 'Lowers', href: '/Products/lowers', role: null },
{ name: 'Uppers', href: '/Products/uppers', role: null },
{ name: 'Optics', href: '/Products/optics', role: null },
{ name: 'Accessories', href: '/Products/accessories', role: null },
{ name: 'Suppressors', href: '/Products/suppressors', role: null },
{ name: 'Builder', href: '/Builder', role: "All" },
{ name: 'Lowers', href: '/Products/lowers', role: "All" },
{ name: 'Uppers', href: '/Products/uppers', role: "All" },
{ name: 'Optics', href: '/Products/optics', role: "All" },
{ name: 'Accessories', href: '/Products/accessories', role: "All" },
{ name: 'Suppressors', href: '/Products/suppressors', role: "All" },
],
admin: [
{ name: 'Users', href: '/Admin/Users', role: "Admin" },
{ name: 'Accounts', href: '/Admin/Accounts', role: "Admin" },
],
account: [
{ name: 'Accounts', href: '/Admin/Accounts', role: null },
{ name: 'My Account', href: '/MyAccount', role: null },
{ name: 'Register', href: '/login', role: null },
{ name: 'Guides', href: '/Guides', role: null },
{ name: 'My Account', href: '/MyAccount', role: "All" },
{ name: 'Register', href: '/login', role: "All" },
{ name: 'Guides', href: '/Guides', role: "All" },
],
about: [
{ name: 'About', href: '/About', role: null },
{ name: 'Blog', href: '/Blog', role: null },
{ name: 'Jobs', href: '/Jobs', role: null },
{ name: 'Press', href: '/Press', role: null },
{ name: 'Contact', href: '/Contact', role: null },
{ name: 'About', href: '/About', role: "All" },
{ name: 'Blog', href: '/Blog', role: "All" },
{ name: 'Jobs', href: '/Jobs', role: "All" },
{ name: 'Press', href: '/Press', role: "All" },
{ name: 'Contact', href: '/Contact', role: "All" },
],
legal: [
{ name: 'Terms of service', href: '/TOS', role: null },
{ name: 'Privacy policy', href: '/PP', role: null },
{ name: 'Affiliate Disclosure', href: '/Disclosure', role: null },
{ name: 'Terms of service', href: '/TOS', role: "All" },
{ name: 'Privacy policy', href: '/PP', role: "All" },
{ name: 'Affiliate Disclosure', href: '/Disclosure', role: "All" },
],
social: [
{
name: 'Facebook',
href: '#',
role: null,
icon: (props: any) => (
role: "All",
icon: (props: React.SVGProps<SVGSVGElement>) => (
<svg fill="currentColor" viewBox="0 0 24 24" {...props}>
<path
fillRule="evenodd"
@@ -51,8 +51,8 @@ const navigation = {
{
name: 'Instagram',
href: '#',
role: null,
icon: (props: any) => (
role: "All",
icon: (props: React.SVGProps<SVGSVGElement>) => (
<svg fill="currentColor" viewBox="0 0 24 24" {...props}>
<path
fillRule="evenodd"
@@ -65,8 +65,8 @@ const navigation = {
{
name: 'X',
href: '#',
role: null,
icon: (props: any) => (
role: "All",
icon: (props: React.SVGProps<SVGSVGElement>) => (
<svg fill="currentColor" viewBox="0 0 24 24" {...props}>
<path d="M13.6823 10.6218L20.2391 3H18.6854L12.9921 9.61788L8.44486 3H3.2002L10.0765 13.0074L3.2002 21H4.75404L10.7663 14.0113L15.5685 21H20.8131L13.6819 10.6218H13.6823ZM11.5541 13.0956L10.8574 12.0991L5.31391 4.16971H7.70053L12.1742 10.5689L12.8709 11.5655L18.6861 19.8835H16.2995L11.5541 13.096V13.0956Z" />
</svg>
@@ -75,8 +75,8 @@ const navigation = {
{
name: 'YouTube',
href: '#',
role: null,
icon: (props: any) => (
role: "All",
icon: (props: React.SVGProps<SVGSVGElement>) => (
<svg fill="currentColor" viewBox="0 0 24 24" {...props}>
<path
fillRule="evenodd"
@@ -95,8 +95,7 @@ export default async function Footer() {
const { session, user } = await validateRequest();
const userId = user?.id ?? '';
let hasAdminFlag:boolean = false;
console.log("console log:"+ userId);
console.log(user?.email);
if(session != null) {
hasAdminFlag = (await isAdmin(userId)) ?? false;
console.log("admin?:" + hasAdminFlag);
@@ -106,7 +105,7 @@ export default async function Footer() {
return (
<footer className="bg-zinc-900">
<div className="bg-white">{userId}should be something here</div>
<div className="bg-white"></div>
<div className="mx-auto max-w-7xl px-6 pb-8 pt-20 sm:pt-24 lg:px-8 lg:pt-32">
<div className="xl:grid xl:grid-cols-3 xl:gap-8">
<div className="grid grid-cols-2 gap-8 xl:col-span-2">
@@ -213,7 +212,7 @@ export default async function Footer() {
{navigation.social.map((item) => (
<a key={item.name} href={item.href} className="text-gray-400 hover:text-gray-300">
<span className="sr-only">{item.name}</span>
<item.icon aria-hidden="true" className="size-6" />
<item.icon aria-hidden="true" className={"size-6"} />
</a>
))}
</div>

View File

@@ -1,6 +1,3 @@
import { clerkMiddleware } from "@clerk/nextjs/server";
export default clerkMiddleware();
export const config = {
matcher: [
@@ -17,7 +14,7 @@ import { verifyRequestOrigin } from "lucia";
import { NextResponse } from "next/server";
import type { NextRequest } from "next/server";
export async function middleware(request: NextRequest): Promise<NextResponse> {
export default async function middleware(request: NextRequest): Promise<NextResponse> {
if (request.method === "GET") {
return NextResponse.next();
}