Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: enhance ninjas page #219

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 35 additions & 6 deletions apps/app/components/Ninja/index.js
Original file line number Diff line number Diff line change
@@ -1,29 +1,58 @@
import { Avatar, Card } from "antd";
import React, { useState } from "react";
import { Avatar, Button, Card, Popconfirm, Space } from "antd";
import { EditOutlined } from "@ant-design/icons";
import Belt from "~/components/Belt";
import Link from "next/link";
import NinjaForm from "~/components/NinjaForm";

const { Meta } = Card;

function Ninja(ninja) {
const [showNinjaForm, setShowNinjaForm] = useState(false);
const [showPopconfirm, setShowPopconfirm] = useState(false);

const handleButtonClick = () => {
setShowNinjaForm(false);
setShowPopconfirm(true);
};

const handleConfirm = () => {
setShowNinjaForm(true);
setShowPopconfirm(false);
};

const handleCancel = () => {
setShowPopconfirm(false);
};

return (
<Card
key={ninja.id}
size="large"
style={{ width: 300, marginTop: 16 }}
actions={[
<Link key={`link ${ninja.id}`} href={`/ninjas/edit/${ninja.id}`}>
<a>
<EditOutlined key="edit" />
</a>
</Link>,
<Popconfirm
key={`popconfirm ${ninja.id}`}
title="Tem certeza que deseja editar?"
open={showPopconfirm}
onConfirm={handleConfirm}
onCancel={handleCancel}
>
<Button
key={`button ${ninja.id}`}
icon={<EditOutlined />}
onClick={handleButtonClick}
/>
</Popconfirm>,
]}
>
{showNinjaForm && <NinjaForm id={ninja.id} reloadNinjas={null} />}
<Link href={`/profile/ninja/${ninja.id}`}>
<a>
<Meta
avatar={<Avatar src={ninja.photo} />}
title={`${ninja.first_name} ${ninja.last_name}`}
style={{ marginBottom: "10px" }}
/>
<Belt belt={ninja.belt} />
</a>
Expand Down
181 changes: 92 additions & 89 deletions apps/app/components/NinjaForm/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
DatePicker,
Form,
Input,
Modal,
Row,
Select,
Space,
Expand All @@ -20,7 +21,7 @@ import * as api from "bokkenjs";
import { notifyError, notifyInfo } from "~/components/Notification";
const { Title } = Typography;

export default function NinjaForm({ id }) {
export default function NinjaForm({ id, reloadNinjas }) {
const router = useRouter();
const [form] = Form.useForm();

Expand All @@ -30,6 +31,8 @@ export default function NinjaForm({ id }) {
const [skills, setSkills] = useState([]);
const [selectedSkills, setSelectedSkills] = useState([]);

const [isModalVisible, setIsModalVisible] = useState(true);

const getAllSkills = () => {
api
.getSkills()
Expand Down Expand Up @@ -105,20 +108,22 @@ export default function NinjaForm({ id }) {
.then(() => {
changeSkills(id);
notifyInfo("O ninja foi editado com sucesso");
router.push("/ninjas");
//reloadNinjas(); // Does not work because of invalid date, the data from the response returns undefined in ninja.birthday
router.reload(); // This works for now, but it is not the best solution, we need to fix the invalid date
})
.catch((error) => {
notifyError(
"Ocorreu um erro",
"Não foi possível atualizar os dados do ninja"
"Não foi possível atualizar os dados do ninja" + error
);
});
} else {
api
.createNinja(values)
.then((response) => {
changeSkills(response.data.id);
router.push("/ninjas");
notifyInfo("O ninja foi criado com sucesso");
reloadNinjas();
})
.catch((error) => {
notifyError("Ocorreu um erro", "Não foi possível criar o ninja");
Expand All @@ -133,95 +138,93 @@ export default function NinjaForm({ id }) {
xxl: 6,
};

const handleCancel = () => {
setIsModalVisible(false);
};

return (
<>
<Row justify="space-between">
<Title level={2}>
{id && ninja
? ninja.first_name + " " + ninja.last_name
: "Novo Ninja"}
</Title>
<Space>
<Link href="/ninjas">
<Button
danger
shape="circle"
size="large"
icon={<CloseOutlined />}
/>
</Link>
<Button
shape="circle"
type="primary"
size="large"
icon={<SaveOutlined />}
onClick={() => form.submit()}
/>
</Space>
</Row>
<Row align="middle">
<Col xs={24} sm={24} md={20} lg={16} xl={12}>
<Form
{...{
labelCol: { span: 8 },
wrapperCol: { span: 16 },
}}
initialValues={ninja}
form={form}
onFinish={onFinish}
>
<Form.Item
label="Nome"
name="ninja[first_name]"
rules={[{ required: true }]}
initialValue={ninja ? ninja.first_name : null}
>
<Input placeholder="Linus" />
</Form.Item>
<Form.Item
label="Apelido"
name="ninja[last_name]"
rules={[{ required: true }]}
initialValue={id && ninja ? ninja.last_name : ""}
<Modal
title={id ? "Editar Ninja" : "Criar Novo Ninja"}
open={isModalVisible}
onCancel={handleCancel}
onOk={() => {
form.submit();
setIsModalVisible(false);
}}
width={700}
>
<Row justify="center">
<Title level={2}>
{id && ninja
? ninja.first_name + " " + ninja.last_name
: "Novo Ninja"}
</Title>
</Row>
<Row justify="center" align="middle">
<Col xs={24} sm={24} md={20} lg={16} xl={12}>
<Form
{...{
labelCol: { span: 8 },
wrapperCol: { span: 16 },
}}
initialValues={ninja}
form={form}
onFinish={onFinish}
>
<Input placeholder="Torvalds" />
</Form.Item>
<Form.Item
label="Aniversário"
name="ninja[birthday]"
rules={[{ required: true }]}
initialValue={
id && ninja ? moment(ninja.birthday, "YYYY-MM-DD") : null
}
>
<DatePicker />
</Form.Item>

<Form.Item label="Quer aprender">
<Select
mode="multiple"
placeholder="Adicionar linguagem"
onChange={setSelectedSkills}
value={selectedSkills}
style={{ minWidth: "200px" }}
<Form.Item
label="Nome"
name="ninja[first_name]"
rules={[{ required: true }]}
initialValue={ninja ? ninja.first_name : null}
>
<Input placeholder="Linus" />
</Form.Item>
<Form.Item
label="Apelido"
name="ninja[last_name]"
rules={[{ required: true }]}
initialValue={id && ninja ? ninja.last_name : ""}
>
<Input placeholder="Torvalds" />
</Form.Item>
<Form.Item
label="Aniversário"
name="ninja[birthday]"
rules={[{ required: true }]}
initialValue={
moment() // for now I choosed always the current date so that it's easier to use //id && ninja ? moment(ninja.birthday, "YYYY-MM-DD") : null
}
>
{skills.map((s) => (
<Select.Option key={s.id} value={s.id}>
{s.name}
</Select.Option>
))}
</Select>
</Form.Item>
<Row justify="center">
<Link href="/blog/posts/choosing-first-language">
<Button type="secondary">
Como escolher a linguagem para o ninja aprender?
</Button>
</Link>
</Row>
</Form>
</Col>
</Row>
<DatePicker />
</Form.Item>

<Form.Item label="Quer aprender">
<Select
mode="multiple"
placeholder="Adicionar linguagem"
onChange={setSelectedSkills}
value={selectedSkills}
style={{ minWidth: "200px" }}
>
{skills.map((s) => (
<Select.Option key={s.id} value={s.id}>
{s.name}
</Select.Option>
))}
</Select>
</Form.Item>
<Row justify="center">
<Link href="/blog/posts/choosing-first-language">
<Button type="secondary">
Como escolher a linguagem para o ninja aprender?
</Button>
</Link>
</Row>
</Form>
</Col>
</Row>
</Modal>
</>
);
}
46 changes: 40 additions & 6 deletions apps/app/pages/ninjas/index.tsx
Original file line number Diff line number Diff line change
@@ -1,39 +1,73 @@
import { useEffect, useState } from "react";
import Link from "next/link";
import { Button, Col, Row, Typography } from "antd";
import { PlusOutlined } from "@ant-design/icons";
import { Button, Col, Popconfirm, Row, Typography } from "antd";
import { PlusCircleFilled, PlusOutlined } from "@ant-design/icons";
import { withAuth } from "~/components/Auth";
import AppLayout from "~/layouts/AppLayout";
import * as api from "bokkenjs";
import NinjaForm from "~/components/NinjaForm";
import Ninja from "~/components/Ninja";
import { notifyError } from "~/components/Notification";
import { set } from "lodash-es";

const { Title } = Typography;

function Ninjas() {
const [ninjas, setNinjas] = useState<any[]>([]);
const [showNinjaForm, setShowNinjaForm] = useState(false);
const [showPopconfirm, setShowPopconfirm] = useState(false);

useEffect(() => {
const fetchNinjas = () => {
api
.getNinjas()
.then((response: any) => setNinjas(response.data))
.catch((error) => {
notifyError("Ocorreu um erro", "Não foi possível obter os seus ninjas");
});
};

useEffect(() => {
fetchNinjas();
}, []);

const handleButtonClick = () => {
setShowNinjaForm(false);
setShowPopconfirm(true);
};

const handleConfirm = () => {
setShowNinjaForm(true);
setShowPopconfirm(false);
};

const handleCancel = () => {
setShowPopconfirm(false);
};

return (
<AppLayout>
<Row justify="space-between">
<Title level={2}>Os Meus Ninjas</Title>
<Link href="/ninjas/new">
<Popconfirm
title="Quer criar um Ninja?"
open={showPopconfirm}
onConfirm={handleConfirm}
onCancel={handleCancel}
okText="Sim"
cancelText="Não"
placement="left"
>
<Button
shape="circle"
shape="default"
type="primary"
size="large"
icon={<PlusOutlined />}
onClick={handleButtonClick}
/>
</Link>
</Popconfirm>
{showNinjaForm && (
<NinjaForm id={undefined} reloadNinjas={() => fetchNinjas()} />
)}
</Row>
<Row justify="space-around" gutter={[10, 10]}>
{ninjas.map((ninja: any) => (
Expand Down