Skip to content

Commit

Permalink
[WIP][FEATURE] Collection and Cards Form (#140)
Browse files Browse the repository at this point in the history
* feat(CollectionForm): create basic collection form template

* feat(CollectionForm): modularize collection form components

* feat(CollectionForm): refactor Select TextField Types and Cards model

* feat(CollectionForm): create card form

* feat(CollectionForm): rename collectionFormView, refactor CollectionForm and create.tsx

* feat(CollectionForm): add categories array example

* feat(CollectionForm): add delete button with styles

* feat(CollectionForm): add fetch onSubmit

* fix: restore tags to avoid conflicts

* fix> add validation to collections without tags

* fix prettier

Co-authored-by: Agustin Vazquez <[email protected]>
  • Loading branch information
iarabaya and 9gustin authored Sep 12, 2022
1 parent f56f361 commit 15bd196
Show file tree
Hide file tree
Showing 10 changed files with 283 additions and 13 deletions.
79 changes: 79 additions & 0 deletions modules/Cards/components/CardForm.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import { Button, Container, Divider, Stack, Text } from "@chakra-ui/react";
import React from "react";
import { CardData } from "../models";
import { useForm, Controller } from "react-hook-form";
import TextField from "@/modules/shared/components/TextField";
import Trash from "@/modules/shared/components/Icons/Trash";

const CardForm = ({ update, index, value, remove, control }: any) => {
const { handleSubmit } = useForm<CardData>({
defaultValues: value,
});
// const { handleSubmit } = useFormWithYup<CardData>(cardDataSchema);

const onSubmit = async (data: any) => {
console.log(data);
};

console.log(value);
return (
<Container maxW="container.xl">
<Divider />

<Stack py={8} spacing={12} onSubmit={handleSubmit(onSubmit)}>
<Stack spacing={6}>
<Text variant="label" as="label">
Tarjeta número {index + 1}
</Text>

<Controller
control={control}
name="sideA"
render={({ field: { onChange, value, ref } }) => (
<TextField
label="Lado A"
placeholder="Ingrese una pregunta"
onChange={() => console.log(value)}
value={value}
/>
)}
/>

<Controller
control={control}
name="sideB"
render={({ field: { onChange, value, ref } }) => (
<TextField
label="Lado B"
placeholder="Ingrese una pregunta"
onChange={() => console.log(value)}
value={value}
/>
)}
/>

<button
type="button"
onClick={handleSubmit((data) => {
update(index, data);
})}
>
guardar tarjeta
</button>
<Button
variant="outline"
colorScheme="red"
leftIcon={<Trash color="red" height={20} width={20} />}
size="sm"
type="button"
onClick={() => remove(index)}
>
Borrar
</Button>
</Stack>
</Stack>
</Container>
);
};

export default CardForm;
4 changes: 2 additions & 2 deletions modules/Cards/models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ interface CardSide {
}

export interface CardData {
name: string;
createdAt: string;
name?: string;
createdAt?: string;
sideA: CardSide;
sideB: CardSide;
}
Expand Down
135 changes: 135 additions & 0 deletions modules/Collections/components/CollectionForm.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
import CardForm from "@/modules/Cards/components/CardForm";
import TextField from "@/modules/shared/components/TextField";
import Select from "@/modules/shared/components/Select";
import { Button, Center, Container, Stack, Text } from "@chakra-ui/react";
import React from "react";
import { useForm, useFieldArray, Controller } from "react-hook-form";
import { CollectionFirebaseData } from "../models";
import { createCollectionSchema } from "../schema";
import { categories } from "../utils/categories";
import { CardData } from "@/modules/Cards/models";

interface CollectionForm {
title: string;
description: string;
category: string;
cards: CardData[];
}

const fieldArrayName = "cards";

//{ sideA: { type: "text", value: "" }, sideB: { type: "text", value: "" } }
const CollectionForm = () => {
const { control, handleSubmit } = useForm<CollectionForm>({
defaultValues: {
title: "",
description: "",
cards: [{ sideA: { type: "text", value: "" }, sideB: { type: "text", value: "" } }],
category: "",
},
});

const { fields, append, update, remove } = useFieldArray({
control,
name: fieldArrayName,
});

const onSubmit = async (data: CollectionForm) => {
try {
let result = await fetch("/api/collections", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(data),
});
result = await result.json();
window.alert("Collection created");
return result;
} catch (error) {
window.alert("ERROR :(");
return null;
}
};

// const watchFieldArray = watch(fieldArrayName);
// const controlledFields = fields.map((field, index) => {
// return {
// ...field,
// ...watchFieldArray[index],
// };
// });

return (
<Container maxW="container.xl">
<Center>
<Stack as="form" py={8} spacing={12} onSubmit={handleSubmit(onSubmit)}>
<Stack spacing={6}>
<Controller
control={control}
name="title"
render={({ field: { onChange, value, ref } }) => (
<TextField
label="Título"
placeholder="Ingresa un título"
onChange={onChange}
value={value}
/>
)}
/>

<Controller
control={control}
name="category"
render={({ field: { onChange, value, ref } }) => (
<Select label="Categoria" option={categories} onChange={onChange} value={value} />
)}
/>

<Controller
control={control}
name="description"
render={({ field: { onChange, value, ref } }) => (
<TextField
label="Descripción"
placeholder="Ingrese una descripción"
onChange={onChange}
value={value}
/>
)}
/>

{fields.length ? <Text variant="label">Crear Tarjetas</Text> : null}

{fields.map((field, index) => (
<fieldset key={field.id}>
<CardForm
control={control}
update={update}
index={index}
value={field}
remove={remove}
/>
</fieldset>
))}

<Button
type="button"
variant="outline"
onClick={() => {
append({
sideA: { value: "", type: "text" },
sideB: { value: "", type: "text" },
});
}}
>
Añadir tarjeta
</Button>
</Stack>

<Button type="submit">Crear coleccion</Button>
</Stack>
</Center>
</Container>
);
};

export default CollectionForm;
16 changes: 16 additions & 0 deletions modules/Collections/components/CollectionFormsView.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import React, { useState } from "react";
import CollectionForm from "./CollectionForm";
import CardForm from "@/modules/Cards/components/CardForm";

const CollectionFormsView = () => {
// si no tiene estado crea una nueva coleccion
// si recibe estado deberia actualizar una coleccion

return (
<div>
<CollectionForm />
</div>
);
};

export default CollectionFormsView;
4 changes: 3 additions & 1 deletion modules/Collections/hooks/useFilterUserCollections.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@ export default function useFilterUserCollection(userCollections: UserCollections
const regExp = new RegExp(query, "gi");

const result = userCollections.filter((collection) => {
return regExp.test(collection.title) || getTagMatch(collection.tags!, regExp);
return (
regExp.test(collection.title) || (collection.tags && getTagMatch(collection.tags, regExp))
);
});

setFilteredCollections(result);
Expand Down
1 change: 1 addition & 0 deletions modules/Collections/utils/categories.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const categories = ["Medicina", "Biologia", "Matematicas", "Fisica", "Computacion"];
6 changes: 3 additions & 3 deletions modules/shared/components/Icons/Trash.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ export default function Trash({ color, height, width }: IconProps) {
<path
d="M4 7H20M10 11V17M14 11V17M5 7L6 19C6 19.5304 6.21071 20.0391 6.58579 20.4142C6.96086 20.7893 7.46957 21 8 21H16C16.5304 21 17.0391 20.7893 17.4142 20.4142C17.7893 20.0391 18 19.5304 18 19L19 7M9 7V4C9 3.73478 9.10536 3.48043 9.29289 3.29289C9.48043 3.10536 9.73478 3 10 3H14C14.2652 3 14.5196 3.10536 14.7071 3.29289C14.8946 3.48043 15 3.73478 15 4V7"
stroke={color}
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
);
Expand Down
8 changes: 6 additions & 2 deletions modules/shared/components/Select.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from "react";

import { Select, SelectProps } from "@chakra-ui/react";
import { Select, SelectProps, Text } from "@chakra-ui/react";

interface Props extends SelectProps {
option: string[];
Expand All @@ -10,7 +10,11 @@ interface Props extends SelectProps {
const ComponentSelect = ({ label, option, ...props }: Props) => {
return (
<>
<label htmlFor={label}>{label}</label>
<label htmlFor={label}>
<Text variant="label" as="label">
{label}
</Text>
</label>
<Select {...props} placeholder="Select option">
{option.map((item) => {
return (
Expand Down
34 changes: 29 additions & 5 deletions modules/shared/components/TextField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,25 @@ interface TextFiedProps {
variant?: string;
textarea?: boolean;
iconName?: string;
value: string;
onChange: (e: React.FormEvent<HTMLInputElement | HTMLTextAreaElement>) => void;
}

interface InputFieldProps {
placeholder: string;
variant?: string;
iconName?: string;
value: string;
onChange: (e: React.FormEvent<HTMLInputElement>) => void;
}

const InputField: React.FC<InputFieldProps> = ({ placeholder, variant, iconName }) => {
const InputField: React.FC<InputFieldProps> = ({
placeholder,
variant,
iconName,
onChange,
value,
}) => {
// chakra-icons package not type export * correctly
// @ts-ignore
const Icon = iconName && icons[iconName];
Expand All @@ -31,10 +41,10 @@ const InputField: React.FC<InputFieldProps> = ({ placeholder, variant, iconName
<Icon fill="none" w={7} h={7} stroke="gray.200" strokeLinecap="square" />
</InputLeftElement>
)}
<Input placeholder={placeholder} variant={variant} />
<Input placeholder={placeholder} variant={variant} value={value} onChange={onChange} />
</InputGroup>
) : (
<Input placeholder={placeholder} variant={variant} />
<Input placeholder={placeholder} variant={variant} value={value} onChange={onChange} />
)}
</Box>
);
Expand All @@ -46,6 +56,8 @@ const TextField: React.FC<TextFiedProps> = ({
textarea,
variant,
iconName,
value,
onChange,
}) => {
return (
<Stack py={3}>
Expand All @@ -54,9 +66,21 @@ const TextField: React.FC<TextFiedProps> = ({
</Text>

{textarea === true ? (
<Textarea placeholder={placeholder} variant={variant} resize="none" />
<Textarea
placeholder={placeholder}
variant={variant}
resize="none"
value={value}
onChange={onChange}
/>
) : (
<InputField placeholder={placeholder} variant={variant} iconName={iconName} />
<InputField
placeholder={placeholder}
variant={variant}
iconName={iconName}
value={value}
onChange={onChange}
/>
)}
</Stack>
);
Expand Down
9 changes: 9 additions & 0 deletions pages/collections/create.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import React from "react";

import CollectionFormsView from "@/modules/Collections/components/CollectionFormsView";

const CreateCollection: React.FC = () => {
return <CollectionFormsView />;
};

export default CreateCollection;

0 comments on commit 15bd196

Please sign in to comment.