feat: add social editing

This commit is contained in:
Kentai Radiquum 2024-09-20 14:27:09 +05:00
parent ed7e365138
commit 61eb728442
Signed by: Radiquum
GPG key ID: 858E8EE696525EED
5 changed files with 237 additions and 12 deletions

View file

@ -23,11 +23,17 @@ export const ENDPOINTS = {
history: `${API_PREFIX}/profile/login/history/all`, // /<user_id>/<page>
change: `${API_PREFIX}/profile/preference/login/change`, // ?login=<url_encoded_string>
},
statusEdit: `${API_PREFIX}/profile/preference/status/edit`,
statsEdit: `${API_PREFIX}/profile/preference/privacy/stats/edit`,
countsEdit: `${API_PREFIX}/profile/preference/privacy/counts/edit`,
socialEdit: `${API_PREFIX}/profile/preference/privacy/social/edit`,
friendRequestsEdit: `${API_PREFIX}/profile/preference/privacy/friendRequests/edit`,
status: `${API_PREFIX}/profile/preference/status/edit`,
privacy: {
stats: `${API_PREFIX}/profile/preference/privacy/stats/edit`,
counts: `${API_PREFIX}/profile/preference/privacy/counts/edit`,
socials: `${API_PREFIX}/profile/preference/privacy/social/edit`,
friendRequests: `${API_PREFIX}/profile/preference/privacy/friendRequests/edit`,
},
socials: {
info: `${API_PREFIX}/profile/preference/social`,
edit: `${API_PREFIX}/profile/preference/social/edit`,
},
}
},
filter: `${API_PREFIX}/filter`,

View file

@ -5,9 +5,10 @@ import { Spinner } from "../Spinner/Spinner";
import useSWR from "swr";
import { ENDPOINTS } from "#/api/config";
import { useEffect, useState } from "react";
import { unixToDate } from "#/api/utils";
import { ProfileEditPrivacyModal } from "./Profile.EditPrivacyModal";
import { ProfileEditStatusModal } from "./Profile.EditStatusModal";
import { unixToDate } from "#/api/utils";
import { ProfileEditSocialModal } from "./Profile.EditSocialModal";
const fetcher = async (url: string) => {
const res = await fetch(url);
@ -30,6 +31,7 @@ export const ProfileEditModal = (props: {
}) => {
const [privacyModalOpen, setPrivacyModalOpen] = useState(false);
const [statusModalOpen, setStatusModalOpen] = useState(false);
const [socialModalOpen, setSocialModalOpen] = useState(false);
const [privacyModalSetting, setPrivacyModalSetting] = useState("none");
const [privacySettings, setPrivacySettings] = useState({
privacy_stats: 9,
@ -152,7 +154,12 @@ export const ProfileEditModal = (props: {
: login}
</p>
</button>
<button className="p-2 text-left rounded-md hover:bg-gray-100">
<button
className="p-2 text-left rounded-md hover:bg-gray-100"
onClick={() => {
setSocialModalOpen(true);
}}
>
<p className="text-lg">Мои социальные сети</p>
<p className="text-base text-gray-500">
укажите ссылки на свои страницы в соц. сетях
@ -291,6 +298,11 @@ export const ProfileEditModal = (props: {
status={status}
setStatus={setStatus}
/>
<ProfileEditSocialModal
isOpen={socialModalOpen}
setIsOpen={setSocialModalOpen}
token={props.token}
/>
</>
);
};

View file

@ -26,10 +26,10 @@ export const ProfileEditPrivacyModal = (props: {
};
const _endpoints = {
privacy_stats: `${ENDPOINTS.user.settings.statsEdit}?token=${props.token}`,
privacy_counts: `${ENDPOINTS.user.settings.countsEdit}?token=${props.token}`,
privacy_social: `${ENDPOINTS.user.settings.socialEdit}?token=${props.token}`,
privacy_friend_requests: `${ENDPOINTS.user.settings.friendRequestsEdit}?token=${props.token}`,
privacy_stats: `${ENDPOINTS.user.settings.privacy.stats}?token=${props.token}`,
privacy_counts: `${ENDPOINTS.user.settings.privacy.counts}?token=${props.token}`,
privacy_social: `${ENDPOINTS.user.settings.privacy.socials}?token=${props.token}`,
privacy_friend_requests: `${ENDPOINTS.user.settings.privacy.friendRequests}?token=${props.token}`,
};
const [loading, setLoading] = useState(false);
@ -51,6 +51,7 @@ export const ProfileEditPrivacyModal = (props: {
setLoading(false);
privacySettings[el.target.name] = el.target.value;
props.setPrivacySettings(privacySettings);
props.setIsOpen(false)
} else {
new Error("failed to send data");
}

View file

@ -0,0 +1,206 @@
"use client";
import { Button, Modal, Label, TextInput } from "flowbite-react";
import { Spinner } from "../Spinner/Spinner";
import { ENDPOINTS } from "#/api/config";
import { useEffect, useState } from "react";
export const ProfileEditSocialModal = (props: {
isOpen: boolean;
setIsOpen: (isOpen: boolean) => void;
token: string;
}) => {
const [loading, setLoading] = useState(false);
const [updating, setUpdating] = useState(false);
const [socials, setSocials] = useState({
vkPage: "",
tgPage: "",
discordPage: "",
instPage: "",
ttPage: "",
});
function _addUrl(username: string, social: string) {
if (!username) {
return "";
}
if (username.startsWith("h")) {
return username;
}
switch (social) {
case "vk":
return `https://vk.com/${username}`;
case "tg":
return `https://t.me/${username}`;
case "inst":
return `https://instagram.com/${username}`;
case "tt":
return `https://tiktok.com/@${username}`;
}
}
function _removeUrl(link: string) {
if (link.startsWith("https://")) {
const split = link.split("/");
return split[split.length - 1];
} else {
return link;
}
}
useEffect(() => {
setLoading(true);
fetch(`${ENDPOINTS.user.settings.socials.info}?token=${props.token}`)
.then((res) => {
if (res.ok) {
return res.json();
}
})
.then((data) => {
setSocials({
vkPage: data.vk_page,
tgPage: data.tg_page,
discordPage: data.discord_page,
instPage: data.inst_page,
ttPage: data.tt_page,
});
setLoading(false);
});
}, [props.isOpen]);
function handleInput(e: any) {
const social = {
...socials,
[e.target.name]: e.target.value
}
setSocials(social);
}
function _setSocialSetting() {
const data = {
vkPage: _removeUrl(socials.vkPage),
tgPage: _removeUrl(socials.tgPage),
discordPage: _removeUrl(socials.discordPage),
instPage: _removeUrl(socials.instPage),
ttPage: _removeUrl(socials.ttPage),
};
setUpdating(true);
fetch(`${ENDPOINTS.user.settings.socials.edit}?token=${props.token}`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(data),
})
.then((res) => {
if (res.ok) {
setUpdating(false);
props.setIsOpen(false);
} else {
new Error("failed to send data");
}
})
.catch((err) => {
console.log(err);
setUpdating(false);
});
}
return (
<Modal
dismissible
show={props.isOpen}
onClose={() => props.setIsOpen(false)}
size={"4xl"}
>
<Modal.Header>Соц. сети</Modal.Header>
<Modal.Body>
<p className="p-2 text-gray-400 border-2 border-gray-200 rounded-md">
Укажите ссылки на свои социальные сети, чтобы другие пользователи
могли с вами связаться
</p>
{loading ? (
<div className="flex items-center justify-center py-8">
<Spinner />
</div>
) : (
<div className="flex flex-col gap-4 py-4">
<div>
<div className="block mb-2">
<Label htmlFor="vk-page" value="ВКонтакте" />
</div>
<TextInput
id="vk-page"
name="vkPage"
onChange={(e) => handleInput(e)}
value={_addUrl(socials.vkPage, "vk")}
placeholder="Ссылка или никнейм"
/>
</div>
<div>
<div className="block mb-2">
<Label htmlFor="tg-page" value="Telegram" />
</div>
<TextInput
id="tg-page"
name="tgPage"
onChange={(e) => handleInput(e)}
value={_addUrl(socials.tgPage, "tg")}
placeholder="Ссылка или никнейм"
/>
</div>
<div>
<div className="block mb-2">
<Label htmlFor="discord-page" value="Discord" />
</div>
<TextInput
id="discord-page"
name="discordPage"
onChange={(e) => handleInput(e)}
value={socials.discordPage}
placeholder="Никнейм"
/>
</div>
<div>
<div className="block mb-2">
<Label htmlFor="inst-page" value="Instagram" />
</div>
<TextInput
id="inst-page"
name="instPage"
onChange={(e) => handleInput(e)}
value={_addUrl(socials.instPage, "inst")}
placeholder="Ссылка или никнейм"
/>
</div>
<div>
<div className="block mb-2">
<Label htmlFor="tt-page" value="TikTok" />
</div>
<TextInput
id="tt-page"
name="ttPage"
onChange={(e) => handleInput(e)}
value={_addUrl(socials.ttPage, "tt")}
placeholder="Ссылка или никнейм"
/>
</div>
</div>
)}
</Modal.Body>
<Modal.Footer>
<Button
color="blue"
onClick={() => _setSocialSetting()}
disabled={updating}
>
Сохранить
</Button>
<Button color="red" onClick={() => props.setIsOpen(false)}>
Отмена
</Button>
</Modal.Footer>
</Modal>
);
};

View file

@ -27,7 +27,7 @@ export const ProfileEditStatusModal = (props: {
function _setStatusSetting() {
setLoading(true);
fetch(`${ENDPOINTS.user.settings.statusEdit}?token=${props.token}`, {
fetch(`${ENDPOINTS.user.settings.status}?token=${props.token}`, {
method: "POST",
headers: {
"Content-Type": "application/json",