mirror of
https://github.com/muerwre/vault-frontend.git
synced 2025-05-09 11:46:41 +07:00
Добавили заметки в сайдбар (#126)
* added notes sidebar * added note dropping and editing * added sidebar navigation * handling sidebarchanges over time * using router back for closing sidebar * fixed tripping inside single sidebar * added superpowers toggle to sidebar * user button opens sidebar now * added profile cover for profile sidebar * removed profile sidebar completely * ran prettier over project * added note not found error literal
This commit is contained in:
parent
fe3db608d6
commit
5d34090238
72 changed files with 1241 additions and 664 deletions
|
@ -1,56 +1,80 @@
|
|||
import React, { useState, VFC } from 'react';
|
||||
import { FC, useCallback, useState, VFC } from 'react';
|
||||
|
||||
import { Card } from '~/components/containers/Card';
|
||||
import { Columns } from '~/components/containers/Columns';
|
||||
import { Filler } from '~/components/containers/Filler';
|
||||
import { Group } from '~/components/containers/Group';
|
||||
import { Padder } from '~/components/containers/Padder';
|
||||
import { Button } from '~/components/input/Button';
|
||||
import { Icon } from '~/components/input/Icon';
|
||||
import { InputText } from '~/components/input/InputText';
|
||||
import { Textarea } from '~/components/input/Textarea';
|
||||
import { HorizontalMenu } from '~/components/menu/HorizontalMenu';
|
||||
import { NoteCard } from '~/components/notes/NoteCard';
|
||||
import { useGetNotes } from '~/hooks/notes/useGetNotes';
|
||||
import { NoteCreationForm } from '~/components/notes/NoteCreationForm';
|
||||
import { useConfirmation } from '~/hooks/dom/useConfirmation';
|
||||
import { NoteProvider, useNotesContext } from '~/utils/providers/NoteProvider';
|
||||
|
||||
import styles from './styles.module.scss';
|
||||
|
||||
interface SettingsNotesProps {}
|
||||
|
||||
const SettingsNotes: VFC<SettingsNotesProps> = () => {
|
||||
const [text, setText] = useState('');
|
||||
const { notes } = useGetNotes('');
|
||||
const List = () => {
|
||||
const { notes, remove, update } = useNotesContext();
|
||||
const confirm = useConfirmation();
|
||||
|
||||
const onRemove = useCallback(
|
||||
async (id: number) => {
|
||||
confirm('Удалить? Это удалит заметку навсегда', () => remove(id));
|
||||
},
|
||||
[remove],
|
||||
);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Padder>
|
||||
<Group horizontal>
|
||||
<HorizontalMenu>
|
||||
<HorizontalMenu.Item active>Новые</HorizontalMenu.Item>
|
||||
<HorizontalMenu.Item>Старые</HorizontalMenu.Item>
|
||||
</HorizontalMenu>
|
||||
<>
|
||||
{notes.map(note => (
|
||||
<NoteCard
|
||||
remove={() => onRemove(note.id)}
|
||||
update={(text, callback) => update(note.id, text, callback)}
|
||||
key={note.id}
|
||||
content={note.content}
|
||||
createdAt={note.created_at}
|
||||
/>
|
||||
))}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
<Filler />
|
||||
const Form: FC<{ onCancel: () => void }> = ({ onCancel }) => {
|
||||
const { create: submit } = useNotesContext();
|
||||
return <NoteCreationForm onSubmit={submit} onCancel={onCancel} />;
|
||||
};
|
||||
|
||||
<InputText suffix={<Icon icon="search" size={24} />} />
|
||||
</Group>
|
||||
</Padder>
|
||||
const SettingsNotes: VFC<SettingsNotesProps> = () => {
|
||||
const [formIsShown, setFormIsShown] = useState(false);
|
||||
|
||||
<Columns>
|
||||
<Card>
|
||||
<Group>
|
||||
<Textarea handler={setText} value={text} />
|
||||
|
||||
<Group horizontal>
|
||||
return (
|
||||
<NoteProvider>
|
||||
<div className={styles.grid}>
|
||||
<div className={styles.head}>
|
||||
{formIsShown ? (
|
||||
<Form onCancel={() => setFormIsShown(false)} />
|
||||
) : (
|
||||
<Group className={styles.showForm} horizontal>
|
||||
<Filler />
|
||||
<Button size="mini">Добавить</Button>
|
||||
<Button
|
||||
onClick={() => setFormIsShown(true)}
|
||||
size="mini"
|
||||
iconRight="plus"
|
||||
color="secondary"
|
||||
>
|
||||
Добавить
|
||||
</Button>
|
||||
</Group>
|
||||
)}
|
||||
</div>
|
||||
<div className={styles.list}>
|
||||
<Group>
|
||||
<Group>
|
||||
<List />
|
||||
</Group>
|
||||
</Group>
|
||||
</Card>
|
||||
|
||||
{notes.map(note => (
|
||||
<NoteCard key={note.id} content={note.content} createdAt={note.created_at} />
|
||||
))}
|
||||
</Columns>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</NoteProvider>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
@import "src/styles/variables";
|
||||
|
||||
.grid {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
z-index: 4;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.head {
|
||||
@include row_shadow;
|
||||
|
||||
width: 100%;
|
||||
padding: $gap;
|
||||
}
|
||||
|
||||
.list {
|
||||
@include row_shadow;
|
||||
|
||||
overflow-y: auto;
|
||||
flex: 1 1;
|
||||
overflow: auto;
|
||||
padding: 10px;
|
||||
}
|
|
@ -1,17 +1,18 @@
|
|||
import { FC } from "react";
|
||||
import { FC } from 'react';
|
||||
|
||||
import { Superpower } from "~/components/boris/Superpower";
|
||||
import { Filler } from "~/components/containers/Filler";
|
||||
import { Group } from "~/components/containers/Group";
|
||||
import { Zone } from "~/components/containers/Zone";
|
||||
import { InputText } from "~/components/input/InputText";
|
||||
import { Textarea } from "~/components/input/Textarea";
|
||||
import { ERROR_LITERAL } from "~/constants/errors";
|
||||
import { ProfileAccounts } from "~/containers/profile/ProfileAccounts";
|
||||
import { useSettings } from "~/utils/providers/SettingsProvider";
|
||||
import { has } from "~/utils/ramda";
|
||||
import { Superpower } from '~/components/boris/Superpower';
|
||||
import { Filler } from '~/components/containers/Filler';
|
||||
import { Group } from '~/components/containers/Group';
|
||||
import { Zone } from '~/components/containers/Zone';
|
||||
import { InputText } from '~/components/input/InputText';
|
||||
import { Textarea } from '~/components/input/Textarea';
|
||||
import { ERROR_LITERAL } from '~/constants/errors';
|
||||
import { ProfileAccounts } from '~/containers/profile/ProfileAccounts';
|
||||
import { useWindowSize } from '~/hooks/dom/useWindowSize';
|
||||
import { useSettings } from '~/utils/providers/SettingsProvider';
|
||||
import { has } from '~/utils/ramda';
|
||||
|
||||
import styles from "./styles.module.scss";
|
||||
import styles from './styles.module.scss';
|
||||
|
||||
interface UserSettingsViewProps {}
|
||||
|
||||
|
@ -20,10 +21,11 @@ const getError = (error?: string) =>
|
|||
|
||||
const UserSettingsView: FC<UserSettingsViewProps> = () => {
|
||||
const { values, handleChange, errors } = useSettings();
|
||||
const { isPhone } = useWindowSize();
|
||||
|
||||
return (
|
||||
<Group>
|
||||
<Group horizontal className={styles.base_info}>
|
||||
<Group horizontal={!isPhone} className={styles.base_info}>
|
||||
<Superpower>
|
||||
<Zone className={styles.avatar} title="Фото">
|
||||
<small>
|
||||
|
@ -33,18 +35,18 @@ const UserSettingsView: FC<UserSettingsViewProps> = () => {
|
|||
</Zone>
|
||||
</Superpower>
|
||||
|
||||
<Zone title="О себе">
|
||||
<Zone title="О себе" className={styles.about}>
|
||||
<Group>
|
||||
<InputText
|
||||
value={values.fullname}
|
||||
handler={handleChange("fullname")}
|
||||
handler={handleChange('fullname')}
|
||||
title="Полное имя"
|
||||
error={getError(errors.fullname)}
|
||||
/>
|
||||
|
||||
<Textarea
|
||||
value={values.description}
|
||||
handler={handleChange("description")}
|
||||
handler={handleChange('description')}
|
||||
title="Описание"
|
||||
/>
|
||||
|
||||
|
@ -75,21 +77,21 @@ const UserSettingsView: FC<UserSettingsViewProps> = () => {
|
|||
<Group>
|
||||
<InputText
|
||||
value={values.username}
|
||||
handler={handleChange("username")}
|
||||
handler={handleChange('username')}
|
||||
title="Логин"
|
||||
error={getError(errors.username)}
|
||||
/>
|
||||
|
||||
<InputText
|
||||
value={values.email}
|
||||
handler={handleChange("email")}
|
||||
handler={handleChange('email')}
|
||||
title="E-mail"
|
||||
error={getError(errors.email)}
|
||||
/>
|
||||
|
||||
<InputText
|
||||
value={values.newPassword}
|
||||
handler={handleChange("newPassword")}
|
||||
handler={handleChange('newPassword')}
|
||||
title="Новый пароль"
|
||||
type="password"
|
||||
error={getError(errors.newPassword)}
|
||||
|
@ -97,7 +99,7 @@ const UserSettingsView: FC<UserSettingsViewProps> = () => {
|
|||
|
||||
<InputText
|
||||
value={values.password}
|
||||
handler={handleChange("password")}
|
||||
handler={handleChange('password')}
|
||||
title="Старый пароль"
|
||||
type="password"
|
||||
error={getError(errors.password)}
|
||||
|
|
|
@ -3,6 +3,10 @@
|
|||
$pad_danger: mix($red, $content_bg, 70%);
|
||||
$pad_usual: mix(white, $content_bg, 10%);
|
||||
|
||||
.about {
|
||||
flex: 4;
|
||||
}
|
||||
|
||||
.wrap {
|
||||
padding: $gap;
|
||||
z-index: 4;
|
||||
|
@ -21,5 +25,5 @@ div.base_info.base_info {
|
|||
}
|
||||
|
||||
.avatar {
|
||||
flex: 0 0 150px;
|
||||
}
|
||||
flex: 1 0 90px;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue