Skip to content

Commit

Permalink
Refactor components
Browse files Browse the repository at this point in the history
refs #49
  • Loading branch information
franthormel committed Aug 3, 2024
1 parent f7570a3 commit 71263b1
Show file tree
Hide file tree
Showing 19 changed files with 157 additions and 56 deletions.
4 changes: 2 additions & 2 deletions app/listings/filters-area.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import ButtonSmallFilled from "@/components/buttons/small/filled";
import ButtonSmallText from "@/components/buttons/small/text";
import FormInput from "@/components/form-input";
import { AREA_FORMATTER } from "@/lib/formatter/area";
import { formatAppend } from "@/lib/formatter/number";

export default function ListingsFilterArea() {
const DEFAULT_MAX = 20;

const minAreaPlaceholder = "None";
const maxAreaPlaceholder = AREA_FORMATTER.format(DEFAULT_MAX);
const maxAreaPlaceholder = formatAppend(DEFAULT_MAX, "sqm.");

return (
<div className="flex flex-col gap-5">
Expand Down
3 changes: 3 additions & 0 deletions app/listings/function.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export function countListingsToSkip(currentPage: number, countPerPage: number) {
return (currentPage - 1) * countPerPage;
}
9 changes: 6 additions & 3 deletions app/listings/list-top.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
import { formatAppend } from "@/lib/formatter/number";

export function ListingsListTop() {
const listingsCount = 7_238;
const listingsCountText = formatAppend(listingsCount, "listings");

return (
<div>
{/* TODO: Count and sort options */}
<div className="basis-14 px-5 py-4 block md:flex md:flex-row border-y-[1px] border-gray-200">
{/* Count */}
{/* TODO: Use actual numbers */}
{/* TODO: Ensure number formatting is correct (use commas to separate)
(refactor (similar to AREA_FORMATTER now) and use NUMBER_FORMATTER) */}
<span className="font-bold md:mr-6">
7,238 listings
{listingsCountText}
</span>
{/* TODO: Sort options */}
<div>
Expand Down
9 changes: 2 additions & 7 deletions app/listings/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,16 @@ import CardListing from "@/components/card-listing";
import Pagination from "@/components/pagination";
import prisma from "@/lib/db";
import { CURRENCY_FORMATTER } from "@/lib/formatter/currency";
import { countListingsToSkip } from "./function";
import { ListingsListTop } from "./list-top";
import { ListingsMap } from "./map";
import { ListingsSearchFilters } from "./search-filters";

const LISTINGS_PER_PAGE = 11;

// TODO: Move to new file (functions.ts)
// TODO: Unit test
function countListingsToSkip(currentPage: number) {
return (currentPage - 1) * LISTINGS_PER_PAGE;
}

export default async function Listings() {
const currentPage = 1;
const listingsToSkip = countListingsToSkip(currentPage);
const listingsToSkip = countListingsToSkip(currentPage, LISTINGS_PER_PAGE);
// Count the number of listings using the givne current pagination option values
const listingsCount = await prisma.listing.count()
// Filter listings using the given pagination and filter options
Expand Down
29 changes: 20 additions & 9 deletions components/buttons-segmented/index.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,30 @@
export interface ButtonsSegmentedProps {
values: string[]
/**
* Valid value is between 0-`n`
* Where `n` is the number of entries in `values` minus one (1).
*/
activeIndex: number
}

// TODO: Correct hover style on currently active segment
export default function ButtonsSegmented(props: ButtonsSegmentedProps) {
return (
<div className="flex w-full">
{props.values.map((value, index, arrayValue) =>
<div key={`button-segmented-${index}`}
className="w-12 cursor-pointer border-y-[1px] border-l-[1px] border-gray-400 py-2 text-center
first:bg-amber-400 last:border-r-[1px] hover:bg-amber-200
first:rounded-l-md last:rounded-r-md"
onClick={(e) => { }}>
{value}
</div>)}
{props.values.map((value, index, arrayValue) => {
const indexIsActive = props.activeIndex === index;
return (
<div key={`button-segmented-${index}`}
className={`w-12 cursor-pointer border-y-[1px] border-l-[1px] border-gray-400 py-2 text-center last:border-r-[1px]
first:rounded-l-md last:rounded-r-md
// Current active index should have background color amber-400 and no change in background color when hovered upon
${indexIsActive && 'bg-amber-400'}
// Other segments must have no background color should change its background color when hovered upon
${!indexIsActive && 'hover:bg-amber-200'} `}
onClick={(e) => { }}>
{value}
</div>
)
})}
</div>
);
}
8 changes: 3 additions & 5 deletions components/buttons-segmented/labelled.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,15 @@
import ButtonsSegmented from ".";
import ButtonsSegmented, { ButtonsSegmentedProps } from ".";

export interface ButtonsSegmentedLabelledProps {
values: string[]
export interface ButtonsSegmentedLabelledProps extends ButtonsSegmentedProps {
label: string
}

// TODO: Story
export default function ButtonsSegmentedLabelled(props: ButtonsSegmentedLabelledProps) {
return (
<div>
<label>{props.label}</label>
<div className="mt-2">
<ButtonsSegmented values={props.values} />
<ButtonsSegmented values={props.values} activeIndex={props.activeIndex} />
</div>
</div>
);
Expand Down
2 changes: 0 additions & 2 deletions components/buttons/small/text.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import { buttonText, buttonType } from "../functions";
import { ButtonProps } from "../types";

// TODO: Story
// TODO: Component
export default function ButtonSmallText(props: ButtonProps) {
const text = buttonText(props.loading) ?? props.text;
const type = buttonType(props.type);
Expand Down
27 changes: 27 additions & 0 deletions components/pagination/function.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/**
*
* Show the previous button only if the current page is not the first page
*
* @param currentPage Current page
* @returns `true` if the previous button should be shown, otherwise false.
*/
export function checkShowPreviousButton(currentPage?: number) {
return currentPage !== undefined && currentPage > 1;
}

/**
* Show the next button only if the current page is not the last page
*
* @param pages Total number of pages
* @param currentPage Current page
* @returns `true` if the next button should be shown, otherwise false.
*/
export function checkShowNextButton(pages: number, currentPage?: number) {
if (currentPage === undefined) {
if (pages !== 1) {
return true;
}
} else {
return currentPage < pages;
}
}
16 changes: 3 additions & 13 deletions components/pagination/index.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { checkShowNextButton, checkShowPreviousButton } from "./function"
import PaginationItemNav from "./item-nav"
import PaginationItemNumber from "./item-number"

Expand All @@ -12,19 +13,8 @@ export interface PaginationProps {
// TODO: Style when many pages (need to break it somewhere, must work for all screen screens)
export default function Pagination(props: PaginationProps) {
const pageNumbers = Array.from({ length: props.pages }, (elem, i) => i + 1)
// Show the previous button only if the current page is not the first page
// TODO: Move to function then unit test
const showPreviousButton = props.currentPage && props.currentPage > 1
// Show the next button only if the current page is not the last page
// TODO: Move to function then unit test
let showNextButton = false;
if (props.currentPage === undefined) {
if (props.pages !== 1) {
showNextButton = true;
}
} else {
showNextButton = props.currentPage < props.pages;
}
const showPreviousButton = checkShowPreviousButton(props.currentPage);
const showNextButton = checkShowNextButton(props.pages, props.currentPage);

return (
<div className="flex gap-3">
Expand Down
12 changes: 0 additions & 12 deletions lib/formatter/area.ts

This file was deleted.

1 change: 0 additions & 1 deletion lib/formatter/currency.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
// FUTURE: Localize and put in env
// TODO: Unit testing
export const CURRENCY_FORMATTER = new Intl.NumberFormat("en-PH", {
style: "currency",
currency: "PHP",
Expand Down
5 changes: 5 additions & 0 deletions lib/formatter/number.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,8 @@
export const NUMBER_FORMATTER = new Intl.NumberFormat("en-PH", {
style: "decimal",
});

export function formatAppend(value: number, append: string) {
const formatted = NUMBER_FORMATTER.format(value);
return `${formatted} ${append}`;
}
3 changes: 2 additions & 1 deletion stories/buttons-segmented/ButtonsSegmented.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ type Story = StoryObj<typeof meta>;

export const Example: Story = {
args: {
values: ["Any", "1", "2", "3", "4", "5+"]
values: ["Any", "1", "2", "3", "4", "5+"],
activeIndex: 0
}
};
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ type Story = StoryObj<typeof meta>;
export const Example: Story = {
args: {
values: ["Any", "1", "2", "3", "4", "5+"],
label: "Options"
label: "Options",
activeIndex: 3,
}
};
1 change: 1 addition & 0 deletions stories/pagination/Pagination.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ export const SinglePage: Story = {
export const ManyPages: Story = {
args: {
pages: 101,
currentPage: 55,
}
};

21 changes: 21 additions & 0 deletions tests/app/listings.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { countListingsToSkip } from "../../app/listings/function";

describe("Listings", () => {
test.each([
{ currentPage: 1, countPerPage: 20, expected: 0 },
{ currentPage: 2, countPerPage: 30, expected: 30 },
{ currentPage: 3, countPerPage: 40, expected: 80 },
{ currentPage: 4, countPerPage: 50, expected: 150 },
{ currentPage: 5, countPerPage: 60, expected: 240 },
{ currentPage: 12, countPerPage: 55, expected: 605 },
{ currentPage: 22, countPerPage: 25, expected: 525 },
{ currentPage: 29, countPerPage: 32, expected: 896 },
{ currentPage: 99, countPerPage: 44, expected: 4312 },
])(
"countListingsToSkip($currentPage, $countPerPage)",
({ currentPage, countPerPage, expected }) => {
const output = countListingsToSkip(currentPage, countPerPage);
expect(output).toBe(expected);
}
);
});
36 changes: 36 additions & 0 deletions tests/components/pagination.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import {
checkShowNextButton,
checkShowPreviousButton,
} from "../../components/pagination/function";

describe("Pagination", () => {
test.each([
{ currentPage: -1, expected: false },
{ currentPage: 0, expected: false },
{ currentPage: 1, expected: false },
{ currentPage: 99, expected: true },
{ currentPage: NaN, expected: false },
{ currentPage: undefined, expected: false },
])("checkShowPreviousButton($currentPage)", ({ currentPage, expected }) => {
const output = checkShowPreviousButton(currentPage);
expect(output).toBe(expected);
});

test.each([
{ pages: 100, currentPage: -1, expected: true },
{ pages: 100, currentPage: 0, expected: true },
{ pages: 100, currentPage: 1, expected: true },
{ pages: 100, currentPage: 99, expected: true },
{ pages: 100, currentPage: 100, expected: false },
{ pages: 100, currentPage: 101, expected: false },
{ pages: 100, currentPage: 201, expected: false },
{ pages: 100, currentPage: NaN, expected: false },
{ pages: 100, currentPage: undefined, expected: true },
])(
"checkShowNextButton($pages, $currentPage)",
({ pages, currentPage, expected }) => {
const output = checkShowNextButton(pages, currentPage);
expect(output).toBe(expected);
}
);
});
12 changes: 12 additions & 0 deletions tests/lib/formatter/currency.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { CURRENCY_FORMATTER } from "../../../lib/formatter/currency";

describe("Currency formatter", () => {
test.each([
{ value: 12.39, expected: "₱12" },
{ value: 2_592.912, expected: "₱2,593" },
{ value: 42_622_884.2837, expected: "₱42,622,884" },
])("format($value)", ({ value, expected }) => {
const output = CURRENCY_FORMATTER.format(value);
expect(output).toBe(expected);
});
});
12 changes: 12 additions & 0 deletions tests/lib/formatter/number.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { formatAppend } from "../../../lib/formatter/number";

describe("Number formatter", () => {
test.each([
{ value: 15, append: "apples", expected: "15 apples" },
{ value: 1_302, append: "MB", expected: "1,302 MB" },
{ value: 1_250_390, append: "units", expected: "1,250,390 units" },
])("formatAppend($value, $append)", ({ value, append, expected }) => {
const output = formatAppend(value, append);
expect(output).toBe(expected);
});
});

0 comments on commit 71263b1

Please sign in to comment.