Skip to content

Commit

Permalink
fdd example
Browse files Browse the repository at this point in the history
  • Loading branch information
chramos committed Mar 31, 2022
1 parent eff16d0 commit 0510c89
Show file tree
Hide file tree
Showing 40 changed files with 3,613 additions and 227 deletions.
9 changes: 8 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,22 @@
"lint": "next lint"
},
"dependencies": {
"axios": "^0.26.1",
"lodash": "^4.17.21",
"next": "12.1.0",
"react": "17.0.2",
"react-dom": "17.0.2"
"react-dom": "17.0.2",
"react-query": "^3.34.16"
},
"devDependencies": {
"@types/lodash": "^4.14.181",
"@types/node": "17.0.21",
"@types/react": "17.0.41",
"autoprefixer": "^10.4.4",
"eslint": "8.11.0",
"eslint-config-next": "12.1.0",
"postcss": "^8.4.12",
"tailwindcss": "^3.0.23",
"typescript": "4.6.2"
}
}
8 changes: 0 additions & 8 deletions pages/_app.tsx

This file was deleted.

13 changes: 0 additions & 13 deletions pages/api/hello.ts

This file was deleted.

72 changes: 0 additions & 72 deletions pages/index.tsx

This file was deleted.

6 changes: 6 additions & 0 deletions postcss.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
}
5 changes: 5 additions & 0 deletions src/api.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import axios from "axios";

const api = axios.create({ baseURL: "https://jsonplaceholder.typicode.com" });

export default api;
41 changes: 41 additions & 0 deletions src/cache-factory.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { isEmpty } from "lodash";
import { QueryKey } from "react-query";
import queryClient from "./query-client";

/**
* @author Henrique Ramos <[email protected]>
* @version 1.0.0
*/
const cacheFactory = (key: QueryKey) => {
return {
remove: (element: any) => {
try {
queryClient.setQueryData(key, (cache: any) =>
cache.filter((item: any) => item.id !== element.id)
);
} catch (error) {}
},
save: (element: any) => {
try {
queryClient.setQueryData(key, (cache: any) => {
const isArray = !isEmpty(cache) && Array.isArray(cache);
if (isArray) {
return cache.some((item: any) => item.id === element.id)
? cache.map((item: any) =>
item.id === element.id ? element : item
)
: [...cache, element];
}
return element;
});
} catch (error) {}
},
invalidate: () => {
try {
queryClient.invalidateQueries(key);
} catch (error) {}
},
};
};

export default cacheFactory;
171 changes: 171 additions & 0 deletions src/components/button.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
import React from "react";
import Spinner from "./spinner";

type ColorScheme =
| "primary"
| "secondary"
| "accent"
| "success"
| "danger"
| "warning"
| "info";
interface ButtonProps {
label: string;
icon?: React.ReactNode;
colorScheme?: ColorScheme | "light";
variant?: "solid" | "outline" | "ghost";
loading?: boolean;
disabled?: boolean;
shape?: "pill" | "rounded";
onClick?: () => void;
grow?: boolean;
type?: "button" | "submit";
}

const Button = ({
label,
icon,
colorScheme = "primary",
variant = "solid",
loading,
disabled,
shape = "rounded",
onClick,
grow,
type = "button",
}: ButtonProps) => {
return (
<button
onClick={() => {
if (loading) {
return;
}
onClick?.();
}}
disabled={disabled}
type={type}
className={`
relative
${grow ? "w-full" : ""}
${
shape === "pill" ? "rounded-full" : "rounded-md"
} transition-all flex justify-center border border-transparent shadow-sm px-4 py-2 text-base font-medium focus:outline-none focus:ring-2 focus:ring-offset-1 sm:col-start-2 sm:text-sm ${
classMap[colorScheme][variant]
} disabled:cursor-not-allowed disabled:bg-gray-200 disabled:text-gray-500 flex items-center disabled:border-gray-200`}
>
{loading ? (
<div className="absolute inset-0 flex justify-center items-center">
{/* @ts-ignore */}
<Spinner colorScheme={spinnerColorMap[colorScheme][variant]} />
</div>
) : null}

{icon}
<div className={loading ? "opacity-0" : ""}>{label}</div>
</button>
);
};

export default Button;

const spinnerColorMap = {
primary: {
solid: "light",
outline: "primary",
ghost: "primary",
},
secondary: {
solid: "light",
outline: "secondary",
ghost: "secondary",
},
accent: {
solid: "light",
outline: "accent",
ghost: "accent",
},
success: {
solid: "light",
outline: "success",
ghost: "success",
},
danger: {
solid: "light",
outline: "danger",
ghost: "danger",
},
warning: {
solid: "light",
outline: "warning",
ghost: "warning",
},
info: {
solid: "light",
outline: "info",
ghost: "info",
},
light: {
solid: "default",
outline: "default",
ghost: "default",
},
};

const classMap = {
primary: {
solid: `bg-indigo-500 border-indigo-500 hover:bg-indigo-800 text-white focus:ring-indigo-200`,
outline:
"bg-transparent border-indigo-500 text-indigo-500 hover:bg-indigo-500 hover:text-white focus:ring-indigo-200",
ghost:
"bg-transparent border-transparent border-0 shadow-none hover:bg-indigo-50 text-indigo-500",
},
secondary: {
solid: `bg-blue-500 border-transparent hover:bg-blue-800 text-white focus:ring-blue-200`,
outline:
"bg-transparent border-blue-500 text-blue-500 hover:bg-blue-500 hover:text-white focus:ring-blue-200",
ghost:
"bg-transparent border-transparent border-0 shadow-none hover:bg-blue-50 text-blue-500",
},
accent: {
solid: `bg-rose-500 border-transparent hover:bg-rose-800 text-white focus:ring-rose-200`,
outline:
"bg-transparent border-rose-500 text-rose-500 hover:bg-rose-500 hover:text-white focus:ring-rose-200",
ghost:
"bg-transparent border-transparent border-0 shadow-none hover:bg-rose-50 text-rose-500",
},
success: {
solid: `bg-green-500 border-transparent hover:bg-green-800 text-white focus:ring-green-200`,
outline:
"bg-transparent border-green-500 text-green-500 hover:bg-green-500 hover:text-white focus:ring-green-200",
ghost:
"bg-transparent border-transparent border-0 shadow-none hover:bg-green-50 text-green-500",
},
danger: {
solid: `bg-red-500 border-transparent hover:bg-red-800 text-white focus:ring-red-200`,
outline:
"bg-transparent border-red-500 text-red-500 hover:bg-red-500 hover:text-white focus:ring-red-200",
ghost:
"bg-transparent border-transparent border-0 shadow-none hover:bg-red-50 text-red-500",
},
warning: {
solid: `bg-yellow-500 border-transparent hover:bg-yellow-800 text-white focus:ring-yellow-200`,
outline:
"bg-transparent border-yellow-500 text-yellow-500 hover:bg-yellow-500 hover:text-white focus:ring-yellow-200",
ghost:
"bg-transparent border-transparent border-0 shadow-none hover:bg-yellow-50 text-yellow-500",
},
info: {
solid: `bg-sky-500 border-transparent hover:bg-sky-800 text-white focus:ring-sky-200`,
outline:
"bg-transparent border-sky-500 text-sky-500 hover:bg-sky-500 hover:text-white focus:ring-sky-200",
ghost:
"bg-transparent border-transparent border-0 shadow-none hover:bg-sky-50 text-sky-500",
},
light: {
solid: `bg-white border-gray-300 hover:bg-gray-100 focus:ring-gray-400`,
outline:
"bg-transparent border-gray-200 hover:bg-gray-100 focus:ring-gray-400",
ghost:
"bg-transparent border-0 hover:bg-gray-100 focus:ring-gray-400 shadow-none",
},
};
13 changes: 13 additions & 0 deletions src/components/column.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import React from "react";

type ColumnProps = {
className?: string;
};
const Column = ({
children,
className,
}: React.PropsWithChildren<ColumnProps>) => {
return <div className={`flex flex-col ${className}`}>{children}</div>;
};

export default Column;
20 changes: 20 additions & 0 deletions src/components/form.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import React from "react";

type FormType = {
onSubmit?: () => void;
};
const Form = ({ children, onSubmit }: React.PropsWithChildren<FormType>) => {
return (
<form
className="flex flex-col grow"
onSubmit={(event) => {
event.preventDefault();
onSubmit?.();
}}
>
{children}
</form>
);
};

export default Form;
Loading

1 comment on commit 0510c89

@vercel
Copy link

@vercel vercel bot commented on 0510c89 Mar 31, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

Please sign in to comment.