1
0
Fork 0
mirror of https://github.com/muerwre/vault-frontend.git synced 2025-06-26 03:28:29 +07:00

removed redux completely

This commit is contained in:
Fedor Katurov 2022-01-09 19:03:01 +07:00
parent 26e6d8d41b
commit a4bb07e9cf
323 changed files with 2464 additions and 3348 deletions

View file

@ -1,11 +1,11 @@
import React, { FC } from "react";
import { IMessage } from "~/redux/types";
import styles from "./styles.module.scss";
import { formatText, getPrettyDate, getURL } from "~/utils/dom";
import { PRESETS } from "~/constants/urls";
import classNames from "classnames";
import { Group } from "~/components/containers/Group";
import markdown from "~/styles/common/markdown.module.scss";
import React, { FC } from 'react';
import { IMessage } from '~/types';
import styles from './styles.module.scss';
import { formatText, getPrettyDate, getURL } from '~/utils/dom';
import { PRESETS } from '~/constants/urls';
import classNames from 'classnames';
import { Group } from '~/components/containers/Group';
import markdown from '~/styles/common/markdown.module.scss';
interface IProps {
message: IMessage;

View file

@ -1,151 +0,0 @@
import React, { FC, Fragment, useCallback, useEffect } from 'react';
import { ISocialProvider } from '~/redux/auth/types';
import styles from './styles.module.scss';
import { Placeholder } from '~/components/placeholders/Placeholder';
import { Icon } from '~/components/input/Icon';
import { Button } from '~/components/input/Button';
import { Group } from '~/components/containers/Group';
import * as AUTH_ACTIONS from '~/redux/auth/actions';
import { selectAuthProfile } from '~/redux/auth/selectors';
import { IState } from '~/redux/store';
import { connect } from 'react-redux';
import { API } from '~/constants/api';
import { ProfileAccountsError } from '~/components/profile/ProfileAccountsError';
const mapStateToProps = (state: IState) => selectAuthProfile(state).socials;
const mapDispatchToProps = {
authGetSocials: AUTH_ACTIONS.authGetSocials,
authDropSocial: AUTH_ACTIONS.authDropSocial,
authAttachSocial: AUTH_ACTIONS.authAttachSocial,
authSetSocials: AUTH_ACTIONS.authSetSocials,
};
type IProps = ReturnType<typeof mapStateToProps> & typeof mapDispatchToProps & {};
const SOCIAL_ICONS: Record<ISocialProvider, string> = {
vkontakte: 'vk',
google: 'google',
};
const ProfileAccountsUnconnected: FC<IProps> = ({
authGetSocials,
authDropSocial,
authAttachSocial,
authSetSocials,
accounts,
is_loading,
error,
}) => {
const onMessage = useCallback(
(event: MessageEvent) => {
if (!event?.data?.type) return;
switch (event?.data?.type) {
case 'oauth_processed':
return authAttachSocial(event?.data?.payload?.token);
case 'oauth_error':
return authSetSocials({ error: event?.data?.payload?.error || '' });
default:
return;
}
},
[authAttachSocial, authSetSocials]
);
const openOauthWindow = useCallback(
(provider: ISocialProvider) => () => {
window.open(API.USER.OAUTH_WINDOW(provider), '', 'width=600,height=400');
},
[]
);
const resetErrors = useCallback(() => authSetSocials({ error: '' }), [authSetSocials]);
useEffect(() => {
authGetSocials();
}, [authGetSocials]);
useEffect(() => {
window.addEventListener('message', onMessage);
return () => window.removeEventListener('message', onMessage);
}, [onMessage]);
return (
<Group className={styles.wrap}>
{error && <ProfileAccountsError onClose={resetErrors} error={error} />}
<Group className={styles.info}>
<p>
Ты можешь входить в Убежище, используя аккаунты на других сайтах вместо ввода логина и
пароля.
</p>
<p>
Мы честно украдём и будем хранить твои имя, фото и адрес на этом сайте, но никому о них не
расскажем.
</p>
</Group>
{is_loading && (
<div className={styles.loader}>
{[...new Array(accounts.length || 1)].map((_, i) => (
<Fragment key={i}>
<Placeholder width="50%" />
<Placeholder width="auto" />
</Fragment>
))}
</div>
)}
{!is_loading && accounts.length > 0 && (
<div className={styles.list}>
{!is_loading &&
accounts.map(it => (
<div className={styles.account} key={`${it.provider}-${it.id}`}>
<div
className={styles.account__photo}
style={{ backgroundImage: it.photo ? `url(${it.photo})` : 'none' }}
>
<div className={styles.account__provider}>
<Icon icon={SOCIAL_ICONS[it.provider]} size={12} />
</div>
</div>
<div className={styles.account__name}>{it.name || it.id}</div>
<div className={styles.account__drop}>
<Icon icon="close" size={22} onClick={() => authDropSocial(it.provider, it.id)} />
</div>
</div>
))}
</div>
)}
<Group horizontal className={styles.buttons}>
<Button
size="small"
type="button"
iconLeft="vk"
color="gray"
onClick={openOauthWindow('vkontakte')}
>
Вконтакте
</Button>
<Button
size="small"
type="button"
iconLeft="google"
color="gray"
onClick={openOauthWindow('google')}
>
Google
</Button>
</Group>
</Group>
);
};
const ProfileAccounts = connect(mapStateToProps, mapDispatchToProps)(ProfileAccountsUnconnected);
export { ProfileAccounts };

View file

@ -1,87 +0,0 @@
@import "src/styles/variables";
.wrap {
}
.list {
border-radius: $radius;
background: transparentize(white, 0.95);
}
.buttons {
background: transparentize(black, 0.8);
border-radius: $radius;
padding: $gap / 2;
display: flex;
align-items: center;
justify-content: flex-end;
}
.add {
//background-color: $content_bg !important;
}
.loader {
display: grid;
grid-row-gap: $gap;
grid-column-gap: $gap * 4;
grid-template-columns: 1fr 32px;
& > div {
height: 48px;
width: auto;
}
}
.account {
display: grid;
grid-template-columns: 20px auto 20px;
grid-column-gap: $gap * 1.5;
align-items: center;
border-bottom: 1px solid transparentize(white, 0.9);
padding: $gap;
&:last-child {
border-bottom: none;
}
&__photo {
width: 28px;
height: 28px;
background: 50% 50% no-repeat;
background-size: cover;
border-radius: 2px;
position: relative;
background: $content_bg;
}
&__provider {
position: absolute;
right: -2px;
bottom: -8px;
background: $content_bg;
}
&__name {
font: $font_16_semibold;
padding-left: $gap / 2;
}
&__drop {
cursor: pointer;
opacity: 0.5;
transition: opacity 0.25s;
fill: $red;
display: flex;
align-items: center;
&:hover {
opacity: 1;
}
}
}
.info {
padding: $gap $gap / 2;
font: $font_14_regular;
}

View file

@ -1,8 +1,8 @@
import React, { FC } from "react";
import styles from "./styles.module.scss";
import { Group } from "~/components/containers/Group";
import { ERROR_LITERAL } from "~/constants/errors";
import { Button } from "~/components/input/Button";
import React, { FC } from 'react';
import styles from './styles.module.scss';
import { Group } from '~/components/containers/Group';
import { ERROR_LITERAL } from '~/constants/errors';
import { Button } from '~/components/input/Button';
interface IProps {
onClose: () => void;

View file

@ -3,7 +3,7 @@ import styles from './styles.module.scss';
import { getURL } from '~/utils/dom';
import { PRESETS } from '~/constants/urls';
import { Icon } from '~/components/input/Icon';
import { IFile } from '~/redux/types';
import { IFile } from '~/types';
export interface ProfileAvatarProps {
canEdit: boolean;

View file

@ -6,24 +6,29 @@ import { Group } from '~/components/containers/Group';
import markdown from '~/styles/common/markdown.module.scss';
import classNames from 'classnames';
import { useProfileContext } from '~/utils/providers/ProfileProvider';
import { useUser } from '~/hooks/auth/useUser';
const ProfileDescription: FC = () => {
const { profile, isLoading } = useProfileContext();
const { user } = useUser();
const isOwn = user?.id === profile?.id;
const description = isOwn ? user.description : profile.description;
const fullName = isOwn ? user.fullname : profile.fullname;
const username = isOwn ? user.username : profile.username;
if (isLoading) return <ProfileLoader />;
return (
<div className={styles.wrap}>
{!!profile?.description && (
{!!description ? (
<Group
className={classNames(styles.content, markdown.wrapper)}
dangerouslySetInnerHTML={{ __html: formatText(profile.description) }}
dangerouslySetInnerHTML={{ __html: formatText(description) }}
/>
)}
{!profile?.description && (
) : (
<div className={styles.placeholder}>
{profile?.fullname || profile?.username} пока ничего не рассказал о себе
{fullName || username} пока ничего не рассказал о себе
</div>
)}
</div>

View file

@ -6,6 +6,8 @@
display: flex;
box-sizing: border-box;
flex-direction: column;
align-items: center;
justify-content: center;
}
.placeholder {

View file

@ -6,22 +6,22 @@ import { Group } from '~/components/containers/Group';
import { Filler } from '~/components/containers/Filler';
import { InputText } from '~/components/input/InputText';
import { ERROR_LITERAL } from '~/constants/errors';
import { ProfileAccounts } from '~/components/profile/ProfileAccounts';
import { ProfileAccounts } from '~/containers/profile/ProfileAccounts';
import classNames from 'classnames';
import { useUser } from '~/hooks/user/userUser';
import { useProfileContext } from '~/utils/providers/ProfileProvider';
import { useUser } from '~/hooks/auth/useUser';
import { useProfileForm } from '~/hooks/profile/useProfileForm';
import { has } from 'ramda';
import { usePatchUser } from '~/hooks/auth/usePatchUser';
const getError = (error?: string) => (error && has(error, ERROR_LITERAL) ? error : undefined);
const ProfileSettings: FC = () => {
const user = useUser();
const { updateProfile } = useProfileContext();
const { user } = useUser();
const { save } = usePatchUser();
const { handleSubmit, values, errors, handleChange } = useProfileForm(
{ ...user, password: '', newPassword: '' },
updateProfile
save
);
return (

View file

@ -1,7 +1,7 @@
import React, { FC } from "react";
import styles from "./styles.module.scss";
import { Icon } from "~/components/input/Icon";
import { Link } from "react-router-dom";
import React, { FC } from 'react';
import styles from './styles.module.scss';
import { Icon } from '~/components/input/Icon';
import { Link } from 'react-router-dom';
interface IProps {
path: string;

View file

@ -1,8 +1,8 @@
import React, { FC } from "react";
import { ProfileSettings } from "~/components/profile/ProfileSettings";
import styles from "./styles.module.scss";
import { Filler } from "~/components/containers/Filler";
import { Button } from "~/components/input/Button";
import React, { FC } from 'react';
import { ProfileSettings } from '~/components/profile/ProfileSettings';
import styles from './styles.module.scss';
import { Filler } from '~/components/containers/Filler';
import { Button } from '~/components/input/Button';
interface IProps {}