FEAT: Users can now edit their own user bios
This commit is contained in:
@@ -29,6 +29,8 @@ const UserPage: React.FC = () => {
|
|||||||
const { showAuthModal, setShowAuthModal } = useAuthModal();
|
const { showAuthModal, setShowAuthModal } = useAuthModal();
|
||||||
const { username: loggedInUsername, profilePicture, setProfilePicture } = useAuth();
|
const { username: loggedInUsername, profilePicture, setProfilePicture } = useAuth();
|
||||||
const initialProfilePicture = useRef(profilePicture);
|
const initialProfilePicture = useRef(profilePicture);
|
||||||
|
const [isEditingBio, setIsEditingBio] = useState(false);
|
||||||
|
const [editedBio, setEditedBio] = useState("");
|
||||||
const { username } = useParams();
|
const { username } = useParams();
|
||||||
const { vods } = useVods(`/api/vods/${username}`);
|
const { vods } = useVods(`/api/vods/${username}`);
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
@@ -110,6 +112,25 @@ const UserPage: React.FC = () => {
|
|||||||
fetchProfileData();
|
fetchProfileData();
|
||||||
}, [fetchProfileData]);
|
}, [fetchProfileData]);
|
||||||
|
|
||||||
|
const saveBio = async () => {
|
||||||
|
try {
|
||||||
|
const response = await fetch("/api/user/bio/change", {
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
body: JSON.stringify({ bio: editedBio }),
|
||||||
|
});
|
||||||
|
|
||||||
|
if (response.ok) {
|
||||||
|
setProfileData(prev => prev ? { ...prev, bio: editedBio } : undefined);
|
||||||
|
setIsEditingBio(false);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error updating bio:", error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
if (!profileData) return <LoadingScreen />;
|
if (!profileData) return <LoadingScreen />;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -205,13 +226,52 @@ const UserPage: React.FC = () => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Bio */}
|
{/* Bio */}
|
||||||
<div className="col-span-1 bg-[var(--user-sideBox)] rounded-lg p-6 grid grid-rows-[auto_1fr] text-center items-center justify-center">
|
<div className="col-span-1 bg-[var(--user-sideBox)] rounded-lg p-6 grid grid-rows-[auto_1fr] w-full">
|
||||||
{/* User Type (e.g., "USER") */}
|
<div className="inline-block px-3 text-center p-1 border border-green-400 rounded-tr-xl rounded-bl-xl rounded-tl-xl rounded-br-xl mx-auto">
|
||||||
<small className="text-green-400 ">{userPageVariant.toUpperCase()}</small>
|
<small className="text-green-400 ">{userPageVariant.toUpperCase()}</small>
|
||||||
|
</div>
|
||||||
<div className="mt-6 text-center">
|
<div className="w-full mt-6 relative flex flex-col items-center">
|
||||||
<h2 className="text-xl font-semibold mb-3">About {profileData.username}</h2>
|
<div className="w-full max-w-full relative flex items-center justify-center">
|
||||||
<p className="text-gray-300 whitespace-pre-wrap">{profileData.bio}</p>
|
<h2 className="text-xl font-semibold mb-3 text-center w-full">About {profileData.username}</h2>
|
||||||
|
{!isEditingBio && userPageVariant === "personal" && (
|
||||||
|
<button
|
||||||
|
onClick={() => {
|
||||||
|
setEditedBio(profileData.bio);
|
||||||
|
setIsEditingBio(true);
|
||||||
|
}}
|
||||||
|
className="absolute right-0 top-0 text-gray-400 hover:text-white transition-colors"
|
||||||
|
>
|
||||||
|
<EditIcon size={20} />
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
{!isEditingBio ? (
|
||||||
|
<p className="text-gray-300 whitespace-pre-wrap text-center w-full">{profileData.bio}</p>
|
||||||
|
) : (
|
||||||
|
<div className="w-full max-w-full">
|
||||||
|
<textarea
|
||||||
|
value={editedBio}
|
||||||
|
onChange={(e) => setEditedBio(e.target.value)}
|
||||||
|
className="w-full bg-white text-black p-2 rounded-lg mb-2 resize-none"
|
||||||
|
maxLength={1024}
|
||||||
|
rows={3}
|
||||||
|
/>
|
||||||
|
<div className="flex justify-end space-x-2 w-full">
|
||||||
|
<Button
|
||||||
|
extraClasses="bg-gray-600 hover:text-white hover:bg-gray-500 hover:border-none active:border-none"
|
||||||
|
onClick={() => setIsEditingBio(false)}
|
||||||
|
>
|
||||||
|
Cancel
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
extraClasses="bg-red-700 hover:text-white hover:bg-red-600 hover:border-none active:border-none"
|
||||||
|
onClick={saveBio}
|
||||||
|
>
|
||||||
|
Save
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -61,6 +61,22 @@ def user_profile_picture_save():
|
|||||||
|
|
||||||
return jsonify({"message": "Profile picture saved", "path": thumbnail_path})
|
return jsonify({"message": "Profile picture saved", "path": thumbnail_path})
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
@user_bp.route('/user/bio/change', methods=['POST'])
|
||||||
|
def user_change_bio():
|
||||||
|
"""
|
||||||
|
Changes users bio
|
||||||
|
"""
|
||||||
|
user_id = session.get("user_id")
|
||||||
|
|
||||||
|
try:
|
||||||
|
data = request.get_json()
|
||||||
|
bio = data.get("bio")
|
||||||
|
update_bio(user_id, bio)
|
||||||
|
return jsonify({"status": "Success"}), 200
|
||||||
|
except Exception as e:
|
||||||
|
return jsonify({"error": str(e)}), 400
|
||||||
|
|
||||||
## Subscription Routes
|
## Subscription Routes
|
||||||
@login_required
|
@login_required
|
||||||
@user_bp.route('/user/subscription/<string:streamer_name>')
|
@user_bp.route('/user/subscription/<string:streamer_name>')
|
||||||
|
|||||||
@@ -27,6 +27,17 @@ def get_username(user_id: str) -> Optional[str]:
|
|||||||
""", (user_id,))
|
""", (user_id,))
|
||||||
return data['username'] if data else None
|
return data['username'] if data else None
|
||||||
|
|
||||||
|
def update_bio(user_id: int, bio: str):
|
||||||
|
"""
|
||||||
|
Updates users bio given their user_id
|
||||||
|
"""
|
||||||
|
with Database() as db:
|
||||||
|
db.execute("""
|
||||||
|
UPDATE users
|
||||||
|
SET bio = ?
|
||||||
|
WHERE user_id = ?
|
||||||
|
""", (bio, user_id))
|
||||||
|
|
||||||
def get_session_info_email(email: str) -> dict:
|
def get_session_info_email(email: str) -> dict:
|
||||||
"""
|
"""
|
||||||
Returns username and user_id given email
|
Returns username and user_id given email
|
||||||
|
|||||||
Reference in New Issue
Block a user