accounts table and many other fixes

This commit is contained in:
2025-01-19 23:49:48 -05:00
parent 26ae83faac
commit e0688a1406
22 changed files with 208 additions and 43 deletions

View File

@@ -3,9 +3,18 @@ import { eq, not , 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";
export const getData = async () => {
const data = await db.select().from(accounts).orderBy(asc(accounts.last_name));
const data = await db.select().from(accounts).orderBy(asc(accounts.userId));
return data;
};
export const getAllAccounts = async () => {
return getData();
};
export const getViewAccounts = async () => {
const data = await db.select().from(vw_accounts).orderBy(asc(vw_accounts.last_name));
return data;
};

View File

@@ -3,8 +3,12 @@ import { eq, not , asc} from "drizzle-orm";
import { revalidatePath } from "next/cache";
import { db } from "../db";
import { componentType } from "@schemas/schema";
export const getData = async () => {
const data = await db.select().from(componentType).orderBy(asc(componentType.name));
return data;
};
export const getComponentTypeName = async () => {
return getData();
};

View File

@@ -10,3 +10,6 @@ export const getData = async () => {
return data;
};
export const getManufacturersName = async () => {
return getData();
};

View File

@@ -8,7 +8,7 @@ export const getData = async () => {
const data = await db.select().from(users).orderBy(asc(users.last_name));
return data;
};
export const getAllUsers = async () => {
export const getAllUsersOrdrByLastname = async () => {
const data = await db.select().from(users).orderBy(asc(users.last_name));
return data;
};

View File

@@ -13,7 +13,6 @@ export default function Blog() {
and exploring firearm parts. Designed for enthusiasts by
enthusiasts, we make firearm building easy and accessible.
</p>
</div>
</section>
)

View File

@@ -13,7 +13,6 @@ export default function Disclosure() {
and exploring firearm parts. Designed for enthusiasts by
enthusiasts, we make firearm building easy and accessible.
</p>
</div>
</section>
)

View File

@@ -8,7 +8,6 @@ export default function Footer() {
<div className="container mx-auto px-6 text-center">
<p>&copy; {new Date().getFullYear()} {constants.APP_NAME}. All rights reserved.</p>
<p>Built by Forward Group </p>
</div>
</footer>
)

View File

@@ -13,7 +13,6 @@ export default function Jobs() {
and exploring firearm parts. Designed for enthusiasts by
enthusiasts, we make firearm building easy and accessible.
</p>
</div>
</section>
)

View File

@@ -13,7 +13,6 @@ export default function About() {
and exploring firearm parts. Designed for enthusiasts by
enthusiasts, we make firearm building easy and accessible.
</p>
</div>
</section>
)

View File

@@ -13,7 +13,6 @@ export default function TOS() {
and exploring firearm parts. Designed for enthusiasts by
enthusiasts, we make firearm building easy and accessible.
</p>
</div>
</section>
)

View File

@@ -1,19 +1,29 @@
import { accounts } from "@schemas/schema";
import { getData } from "@actions/accountActions";
import Account from "@components/Account"; // Adjust the import path as necessary
import React from 'react';
import { getViewAccounts } from "@actions/accountActions";
import AccountsTable from "@src/components/AccountsTable"; // Adjust the import path as necessary
import React, { Suspense } from 'react';
import { ColumnHeadings } from "@src/lib/utils";
import PageHero from "@src/components/PageHero";
export interface AccountProps {
account: any; // Adjust the type according to your data structure
}
export default async function AccountsPage() {
const data = await getData();
const columnHeadings = new ColumnHeadings([
"First Name",
"Last Name",
"Actions",
]);
const data = await getViewAccounts();
return (
<div className="bg-gray-100 min-h-screen flex flex-col">
<Account account={data} />
<div>
<PageHero title="Accounts" />
<div className="container mx-auto">
<Suspense fallback="Loading...">
<AccountsTable data={data} newColumnHeadings={columnHeadings}></AccountsTable>
</Suspense>
</div>
</div>
);
}

View File

@@ -10,7 +10,7 @@ export default async function UsersPage() {
const data = await getData();
const columnHeadings = new ColumnHeadings(['E-mail Address', 'First Name', 'Last Name', 'Blank']);
const columnHeadings = new ColumnHeadings(['E-mail Address', 'First Name', 'Last Name', 'User Name']);
return (
<div>
<PageHero title="Users" />

View File

@@ -0,0 +1,18 @@
import { getOptics } from "@queries/PSA";
import partTypes from 'src/data/parts_cats.json';
import styles from '../styles.module.css';
import PageHero from "@components/PageHero";
import SortTable from "@components/SortTable";
export default async function OpticsPage() {
const psa = await getOptics();
return (
<div>
<PageHero title="Optics" />
<div className="container mx-auto">
<SortTable data={psa}></SortTable>
</div>
</div>
);
}

View File

@@ -1,14 +0,0 @@
import { AccountProps } from "@src/app/Accounts/page";
import React from "react";
export const Account: React.FC<AccountProps> = ({ account }) => {
return (
<div className="account-card">
<h2>{account.name}</h2>
<p>{account.email}</p>
{/* Add more fields as necessary */}
</div>
);
};
export default Account;

View File

@@ -0,0 +1,106 @@
import React from "react";
import { ChevronDownIcon } from "@heroicons/react/20/solid";
import { PlusCircleIcon } from "@heroicons/react/20/solid";
import { ColumnHeadings } from "@src/lib/utils";
import styles from '../styles.module.css';
import PageHero from "@components/PageHero";
import { Suspense } from "react";
import Loading from "@src/app/components/Loading/loading";
import Link from "next/link";
export default async function AccountsTable( props: any ) {
return (
<div className="pb-12">
<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">
<table className="min-w-full divide-y divide-gray-300">
<thead>
<tr>
<th
scope="col"
className="py-3.5 pl-4 pr-3 text-left text-xs font-semibold text-gray-900 "
>
<a href="#" className="group inline-flex">
{props.newColumnHeadings.getHeading()}
<span className="invisible ml-2 flex-none rounded text-gray-400 group-hover:visible group-focus:visible">
<ChevronDownIcon
aria-hidden="true"
className="size-5"
/>
</span>
</a>
</th>
<th
scope="col"
className="px-3 py-3.5 text-left text-xs font-semibold text-gray-900"
>
<a href="#" className="group inline-flex">
{props.newColumnHeadings.getHeading()}
<span className="ml-2 flex-none rounded bg-gray-100 text-gray-900 group-hover:bg-gray-200">
<ChevronDownIcon
aria-hidden="true"
className="size-5"
/>
</span>
</a>
</th>
<th
scope="col"
className="px-3 py-3.5 text-left text-xs font-semibold text-gray-900"
>
<a href="#" className="group inline-flex">
{props.newColumnHeadings.getHeading()}
<span className="ml-2 flex-none rounded bg-gray-100 text-gray-900 group-hover:bg-gray-200">
<ChevronDownIcon
aria-hidden="true"
className="size-5"
/>
</span>
</a>
</th>
</tr>
</thead>
<tbody className=" divide-y divide-gray-200 bg-white">
{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 ">
<Link href={`/userProfile/${item.uuid}`}><span className="pl-2"> {item.first_name}</span></Link>
</td>
<td className="whitespace-nowrap px-3 py-4 text-xs text-gray-900">
{item.last_name}
</td>
<td className="whitespace-nowrap px-3 py-4 text-xs text-gray-900">
<button
type="button"
className="inline-flex items-center gap-x-1.5 rounded-xl bg-lime-800 px-2.5 py-1.5 text-sm font-semibold text-white shadow-sm hover:bg-lime-900 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-lime-900"
>
Edit
<PlusCircleIcon
aria-hidden="true"
className="-mr-0.5 size-5"
/>
</button>
</td>
<td style={{display:'none'}}>
</td>
</tr>
))}
</tbody>
</table>
</div>
</div>
</div>
</div>
);
};

View File

@@ -1,9 +1,9 @@
import Header from "../Header";
import Hero from "../Hero";
import FeaturesSection from "../FeaturesSection";
import About from "../../app/site/About/page";
import Contact from "../../app/site/Contact/page";
import Footer from "../../app/site/Footer/page";
import About from "@siteInfo/About/page";
import Contact from "@siteInfo/Contact/page";
import Footer from "@siteInfo/Footer/page";
export default function HomeContent() {

View File

@@ -101,7 +101,7 @@ export default async function UsersTable(props: any) {
{item.last_name}
</td>
<td className="whitespace-nowrap px-3 py-4 text-xs text-gray-900">
${item.username}
{item.username}
</td>
<td className="whitespace-nowrap px-3 py-4 text-xs text-gray-900">
<button

View File

@@ -12,6 +12,7 @@ const navigation = {
{ name: 'Users', href: '/Admin/Users' },
],
account: [
{ name: 'Accounts', href: '/Accounts' },
{ name: 'My Account', href: '/MyAccount' },
{ name: 'Register', href: '/signin' },
{ name: 'Guides', href: '/Guides' },

View File

@@ -1,14 +1,15 @@
// db/queries.ts
"use server";
import { eq, not , asc} from "drizzle-orm";
import { accounts } from '@schemas/schema'
import { db } from '../../index';
import { accounts } from '@schemas/schema';
import { vw_accounts } from '@schemas/schema';
import { db } from '@db/index';
// Fetch all account
export async function getAllAccounts() {
return await db.select().from(accounts);
}
//@TODO Accounts don't have these fields, i assume next.js auth code did it this way
// Add a new account
export async function addAcount(first_name: string, last_name : string, username : string, password_hash: string ) {
return await db.insert(accounts).values({ first_name, last_name, username, password_hash }).returning();

View File

@@ -102,6 +102,17 @@ export async function getStocks(page = 1) {
.offset(offset);
}
export async function getOptics(page = 1) {
const limit = 40;
const offset = (page - 1) * limit;
return await db.select()
.from(psa)
.limit(limit)
.where(and(like(psa.fineline, "%Optics%")))
.offset(offset);
}
export async function getStocksParts(page = 1) {
const limit = 40;
const offset = (page - 1) * limit;

View File

@@ -1,4 +1,4 @@
import { pgTable, integer, varchar, text, numeric, timestamp, unique, check, bigserial, date, boolean, uuid, bigint, real, doublePrecision, primaryKey } from "drizzle-orm/pg-core"
import { pgTable, integer, varchar, text, numeric, timestamp, unique, check, bigserial, date, boolean, uuid, bigint, real, doublePrecision, primaryKey, pgView } from "drizzle-orm/pg-core"
import { sql } from "drizzle-orm"
export const products = pgTable("products", {
@@ -21,7 +21,7 @@ export const users = pgTable("users", {
.$defaultFn(() => crypto.randomUUID()),
username: varchar({ length: 50 }).notNull(),
email: varchar({ length: 255 }).notNull(),
emailVerifiedOn: timestamp("emailVerifiedOn", { mode: "date" }),
emailVerifiedOn: timestamp("email_verified_on", { mode: "date" }),
password_hash: varchar("password_hash", { length: 255 }).notNull(),
first_name: varchar("first_name", { length: 50 }),
last_name: varchar("last_name", { length: 50 }),
@@ -425,10 +425,11 @@ export const authenticator = pgTable("authenticator", {
});
export const accounts = pgTable("accounts", {
userId: text().notNull(),
uuid: uuid().defaultRandom(),
userId: text("user_id").notNull(),
type: text().notNull(),
provider: text().notNull(),
providerAccountId: text().notNull(),
providerAccountId: text("provider_account_id").notNull(),
refreshToken: text("refresh_token"),
accessToken: text("access_token"),
expiresAt: integer("expires_at"),
@@ -441,3 +442,21 @@ export const accounts = pgTable("accounts", {
accountProviderProviderAccountIdPk: primaryKey({ columns: [table.provider, table.providerAccountId], name: "account_provider_providerAccountId_pk"}),
}
});
export const vw_accounts = pgView("vw_accounts", {
uuid: uuid().defaultRandom(),
userId: text("user_id").notNull(),
type: text().notNull(),
provider: text().notNull(),
providerAccountId: text("provider_account_id").notNull(),
refreshToken: text("refresh_token"),
accessToken: text("access_token"),
expiresAt: integer("expires_at"),
tokenType: text("token_type"),
scope: text(),
idToken: text("id_token"),
sessionState: text("session_state"),
first_name: text("first_name"),
last_name: text("last_name"),
},).existing();

View File

@@ -46,6 +46,9 @@
"./src/components/ui/*",
"./src/components/Brands/*"
],
"@siteInfo/*": [
"./src/app/(siteInfo)/*",
],
"@actions/*": [
"./src/actions/*"
],