Skip to content

Commit

Permalink
🚨 added linting and prettier, fix all, fix run playwright with ci/cd
Browse files Browse the repository at this point in the history
  • Loading branch information
MammaSonnim committed Jul 18, 2024
1 parent 4040857 commit 095f19b
Show file tree
Hide file tree
Showing 32 changed files with 2,406 additions and 188 deletions.
2 changes: 2 additions & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
prettier.config.js
next.config.mjs
17 changes: 17 additions & 0 deletions .eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"parser": "@typescript-eslint/parser",
"parserOptions": {
"project": "./tsconfig.json"
},
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/strict-type-checked",
"plugin:@typescript-eslint/stylistic-type-checked",
"next/core-web-vitals",
"prettier"
],
"rules": {
"@typescript-eslint/restrict-template-expressions": 0,
"@typescript-eslint/unbound-method": 0
}
}
59 changes: 37 additions & 22 deletions .github/workflows/playwright.yml
Original file line number Diff line number Diff line change
@@ -1,27 +1,42 @@
name: Playwright Tests
on:
push:
branches: [ main, master ]
pull_request:
branches: [ main, master ]

on: [push, pull_request]

jobs:
test:
timeout-minutes: 60
runs-on: ubuntu-latest

services:
web:
image: node:16
ports:
- 3000:3000
options: >-
--health-cmd="curl --fail http://localhost:3000 || exit 1"
--health-interval=10s
--health-timeout=5s
--health-retries=3
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: lts/*
- name: Install dependencies
run: npm install -g pnpm && pnpm install
- name: Install Playwright Browsers
run: pnpm exec playwright install --with-deps
- name: Run Playwright tests
run: pnpm exec playwright test
- uses: actions/upload-artifact@v4
if: always()
with:
name: playwright-report
path: playwright-report/
retention-days: 30
- uses: actions/checkout@v2

- name: Set up Node.js
uses: actions/setup-node@v2
with:
node-version: 16

- name: Install dependencies
run: npm ci

- name: Start server
run: npm start &
env:
CI: true

- name: Wait for server to be ready
run: npx wait-on http://localhost:3000

- name: Run Playwright tests
run: npx playwright test
env:
BASE_URL: 'http://localhost:3000'
18 changes: 4 additions & 14 deletions app/dashboard/(overview)/page.tsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,15 @@
import { Suspense } from 'react';
import RevenueChart from '@/app/ui/dashboard/revenue-chart';
import LatestInvoices from '@/app/ui/dashboard/latest-invoices';
import LatestInvoices from '@/app/ui/dashboard/latest-invoices';
import CardWrapper from '@/app/ui/dashboard/cards';
import { lusitana } from '@/app/ui/fonts';
import {
import {
LatestInvoicesSkeleton,
RevenueChartSkeleton,
CardsSkeleton
CardsSkeleton,
} from '@/app/ui/skeletons';
import {
fetchCardData
} from '@/app/lib/data';

export default async function Page() {
const {
totalPaidInvoices,
totalPendingInvoices,
numberOfInvoices,
numberOfCustomers
} = await fetchCardData();

export default function Page() {
return (
<main>
<h1 className={`${lusitana.className} mb-4 text-xl md:text-2xl`}>
Expand Down
2 changes: 1 addition & 1 deletion app/dashboard/invoices/[id]/edit/not-found.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import Link from 'next/link';
import { FaceFrownIcon } from '@heroicons/react/24/outline';

export default function NotFound() {
return (
<main className="flex h-full flex-col items-center justify-center gap-2">
Expand Down
6 changes: 3 additions & 3 deletions app/dashboard/invoices/[id]/edit/page.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { notFound } from 'next/navigation';
import Form from '@/app/ui/invoices/edit-form';
import Breadcrumbs from '@/app/ui/invoices/breadcrumbs';
import { fetchInvoiceById, fetchCustomers } from '@/app/lib/data';;
import { fetchInvoiceById, fetchCustomers } from '@/app/lib/data';

export default async function Page({ params }: { params: { id: string } }) {
const id = params.id;
const [invoice, customers] = await Promise.all([
fetchInvoiceById(id),
fetchCustomers(),
])
]);

if (!invoice) {
notFound();
Expand Down
4 changes: 2 additions & 2 deletions app/dashboard/invoices/create/page.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import Form from '@/app/ui/invoices/create-form';
import Breadcrumbs from '@/app/ui/invoices/breadcrumbs';
import { fetchCustomers } from '@/app/lib/data';

export default async function Page() {
const customers = await fetchCustomers();

return (
<main>
<Breadcrumbs
Expand Down
8 changes: 5 additions & 3 deletions app/dashboard/invoices/error.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ export default function Error({
error,
reset,
}: {
error: Error & { digest?: string },
reset: () => void
error: Error & { digest?: string };
reset: () => void;
}) {
useEffect(() => {
console.error(error);
Expand All @@ -18,7 +18,9 @@ export default function Error({
<h2 className="text-center">Something went wrong!</h2>
<button
className="mt-4 rounded-md bg-blue-500 px-4 py-2 text-sm text-white transition-colors hover:bg-blue-400"
onClick={() => reset()}
onClick={() => {
reset();
}}
>
Try again
</button>
Expand Down
11 changes: 7 additions & 4 deletions app/dashboard/invoices/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { CreateInvoice } from '@/app/ui/invoices/buttons';
import { lusitana } from '@/app/ui/fonts';
import { InvoicesTableSkeleton } from '@/app/ui/skeletons';
import { fetchInvoicesPages } from '@/app/lib/data';

export default async function Page({
searchParams,
}: {
Expand All @@ -15,9 +15,9 @@ export default async function Page({
page?: string;
};
}) {
const query = searchParams?.query || '';
const query = searchParams?.query ?? '';
const currentPage = Number(searchParams?.page) || 1;

const totalPages = await fetchInvoicesPages(query);

return (
Expand All @@ -29,7 +29,10 @@ export default async function Page({
<Search placeholder="Search invoices..." />
<CreateInvoice />
</div>
<Suspense key={query + currentPage} fallback={<InvoicesTableSkeleton />}>
<Suspense
key={`${query}${currentPage}`}
fallback={<InvoicesTableSkeleton />}
>
<Table query={query} currentPage={currentPage} />
</Suspense>
<div className="mt-5 flex w-full justify-center">
Expand Down
6 changes: 4 additions & 2 deletions app/dashboard/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
import SideNav from '@/app/ui/dashboard/sidenav';
import { NotificationProvider } from '@/app/ui/notification-context';
import Notification from '@/app/ui/notification';

export default function Layout({ children }: { children: React.ReactNode }) {
return (
<div className="flex h-screen flex-col md:flex-row md:overflow-hidden">
<div className="w-full flex-none md:w-64">
<SideNav />
</div>
<NotificationProvider>
<div className="flex-grow p-6 md:overflow-y-auto md:p-12">{children}</div>
<div className="flex-grow p-6 md:overflow-y-auto md:p-12">
{children}
</div>
<Notification />
</NotificationProvider>
</div>
Expand Down
31 changes: 19 additions & 12 deletions app/lib/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,15 @@ const FormSchema = z.object({
amount: z.coerce.number(),
status: z.enum(['pending', 'paid']),
date: z.string(),
})
});

const CreateInvoice = FormSchema.omit({ id: true, date: true });

export async function createInvoice(_prevState: ServerActionState, formData: FormData) {
const { customerId, amount, status} = CreateInvoice.parse({
export async function createInvoice(
_prevState: ServerActionState,
formData: FormData,
) {
const { customerId, amount, status } = CreateInvoice.parse({
customerId: formData.get('customerId'),
amount: formData.get('amount'),
status: formData.get('status'),
Expand All @@ -31,7 +34,7 @@ export async function createInvoice(_prevState: ServerActionState, formData: For
INSERT INTO invoices (customer_id, amount, status, date)
VALUES (${customerId}, ${amountInCents}, ${status}, ${date})
`;
} catch(error) {
} catch (error) {
return {
success: false,
message: 'Database Error: Failed to Create Invoice.',
Expand All @@ -43,23 +46,27 @@ export async function createInvoice(_prevState: ServerActionState, formData: For
}

const UpdateInvoice = FormSchema.omit({ id: true, date: true });

export async function updateInvoice(id: string, _prevState: ServerActionState, formData: FormData) {

export async function updateInvoice(
id: string,
_prevState: ServerActionState,
formData: FormData,
) {
const { customerId, amount, status } = UpdateInvoice.parse({
customerId: formData.get('customerId'),
amount: formData.get('amount'),
status: formData.get('status'),
});

const amountInCents = amount * 100;

try {
await sql`
UPDATE invoices
SET customer_id = ${customerId}, amount = ${amountInCents}, status = ${status}
WHERE id = ${id}
`;
} catch(error) {
} catch (error) {
return {
success: false,
message: 'Database Error: Failed to Update Invoice.',
Expand All @@ -72,13 +79,13 @@ export async function updateInvoice(id: string, _prevState: ServerActionState, f

export async function deleteInvoice(id: string) {
try {
await sql`DELETE FROM invoices WHERE id = ${id}`;
} catch(error) {
await sql`DELETE FROM invoices WHERE id = ${id}`;
} catch (error) {
return {
success: false,
message: 'Database Error: Failed to Delete Invoice.',
};
}

revalidatePath('/dashboard/invoices');
}
10 changes: 7 additions & 3 deletions app/lib/data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
} from './definitions';
import { formatCurrency } from './utils';

export async function fetchRevenue() {
export async function fetchRevenue(): Promise<Revenue[] | undefined> {
try {
const data = await sql<Revenue>`SELECT * FROM revenue`;

Expand Down Expand Up @@ -60,7 +60,9 @@ export async function fetchCardData() {

const numberOfInvoices = Number(data[0].rows[0].count ?? '0');
const numberOfCustomers = Number(data[1].rows[0].count ?? '0');
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
const totalPaidInvoices = formatCurrency(data[2].rows[0].paid ?? '0');
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
const totalPendingInvoices = formatCurrency(data[2].rows[0].pending ?? '0');

return {
Expand All @@ -79,7 +81,7 @@ const ITEMS_PER_PAGE = 6;
export async function fetchFilteredInvoices(
query: string,
currentPage: number,
) {
): Promise<InvoicesTable[] | undefined> {
const offset = (currentPage - 1) * ITEMS_PER_PAGE;

try {
Expand Down Expand Up @@ -132,7 +134,9 @@ export async function fetchInvoicesPages(query: string) {
}
}

export async function fetchInvoiceById(id: string) {
export async function fetchInvoiceById(
id: string,
): Promise<InvoiceForm | undefined> {
try {
const data = await sql<InvoiceForm>`
SELECT
Expand Down
Loading

0 comments on commit 095f19b

Please sign in to comment.