Что-то точно поменялось

This commit is contained in:
FEARmeR 2023-05-22 13:00:32 +01:00
parent 820691b1ec
commit 2983c8e741
4 changed files with 276 additions and 40 deletions

View File

@ -5,7 +5,7 @@ import { useWindowsWidth } from "../../assets/js/useWindowsWidth";
// images
import ArrDark from "@/assets/img/down-arrow-dark.svg";
import downArrow from "@/assets/img/down-arrow.svg";
import DownArrWhite from "@/assets/img/down-arrow-white.svg";
const isAuthenticated = computed(() => !!sessionStorage.getItem('access_token')); // Computed property to check if the user is authenticated

View File

@ -0,0 +1,157 @@
<script setup>
import axios from 'axios';
import { onMounted, ref, computed } from "vue";
import NavbarDefault from "../../../examples/navbars/NavbarDefault.vue";
import { useRouter } from "vue-router";
const isAuthenticated = computed(() => !!sessionStorage.getItem('access_token'));
const userId = computed(() => sessionStorage.getItem('user_id'));
const loggedUserName = computed(() => sessionStorage.getItem('username'));
const token = computed(() => sessionStorage.getItem('access_token'));
const profileData = ref([]);
const router = useRouter();
const debugText = ref('');
const getProfile = async () => {
const profileDataRecieved = await axios.get(`http://somebodyhire.me/api/profile/${userId.value}/`);
profileData.value = processProfileData(profileDataRecieved.data);
};
const processProfileData = (data) => {
return {
name: data.name || '',
email: data.email || '',
username: data.username || '',
location: data.location || '',
short_intro: data.short_intro || '',
bio: data.bio || '',
social_github: data.social_github || '',
social_twitter: data.social_twitter || '',
social_vk: data.social_vk || '',
social_youtube: data.social_youtube || '',
social_website: data.social_website || '',
};
};
axios.interceptors.request.use((request) => {
debugText.value += '\n\nRequest:\n' + JSON.stringify(request, null, 2);
return request;
});
axios.interceptors.response.use((response) => {
debugText.value += '\n\nResponse:\n' + JSON.stringify(response, null, 2);
return response;
}, (error) => {
debugText.value += '\n\nResponse Error:\n' + JSON.stringify(error.toJSON(), null, 2);
return Promise.reject(error);
});
const updateProfile = async () => {
try {
const token = computed(() => sessionStorage.getItem('access_token'));
debugText.value = `Type of token: ${typeof token.value}, Value of token: ${token.value}`;
const headers = { 'Authorization': `Bearer ${token.value}` };
await axios.patch(`http://somebodyhire.me/api/profile/${userId.value}/`, profileData.value, { headers });
router.push('/ViewMyProfile');
} catch (error) {
debugText.value = `Error: ${JSON.stringify(error, null, 2)}`;
console.error(error);
}
};
const cancelUpdate = () => {
router.push('/ViewMyProfile');
};
onMounted(async() => {
await getProfile();
});
</script>
<template>
<NavbarDefault />
<div class="profile-container">
<h1>User Profile: {{ loggedUserName }}</h1>
<textarea readonly v-model="debugText"></textarea>
<input type="text" v-model="profileData.username" placeholder="Username">
<input type="email" v-model="profileData.email" placeholder="Email">
<input type="text" v-model="profileData.name" placeholder="Name">
<input type="text" v-model="profileData.short_intro" placeholder="Short Introduction">
<textarea v-model="profileData.bio" placeholder="Biography"></textarea>
<textarea v-model="profileData.social_github" placeholder="GitHub Link"></textarea>
<textarea v-model="profileData.social_twitter" placeholder="Twitter Link"></textarea>
<textarea v-model="profileData.social_vk" placeholder="VK Link"></textarea>
<textarea v-model="profileData.social_youtube" placeholder="YouTube Link"></textarea>
<textarea v-model="profileData.social_website" placeholder="Website Link"></textarea>
<button @click="updateProfile" class="btn-submit">Submit</button>
<button @click="cancelUpdate" class="btn-cancel">Cancel</button>
</div>
</template>
<style scoped>
.profile-container {
display: flex;
flex-direction: column;
align-items: center;
width: 80%;
margin: auto;
padding: 20px;
box-shadow: 0px 0px 10px 0px rgba(0,0,0,0.1);
}
.profile-container img {
width: 100px;
height: 100px;
border-radius: 50%;
object-fit: cover;
margin-bottom: 20px;
}
.profile-container input, .profile-container textarea {
width: 100%; /* Make inputs and textareas take up the full width of the container */
padding: 10px; /* Add some padding */
margin-bottom: 15px; /* Add some margin */
box-sizing: border-box; /* Ensure padding doesn't affect final dimensions */
border: 1px solid #ccc; /* Add a border */
border-radius: 5px; /* Add rounded corners */
}
/* Style for smaller screens */
@media (max-width: 768px) {
.profile-container {
width: 95%;
}
}
.btn-submit {
color: #fff;
background-color: #4CAF50;
border: none;
padding: 15px 32px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 16px;
margin: 4px 2px;
cursor: pointer;
border-radius: 5px;
}
.btn-cancel {
color: #fff;
background-color: #f44336;
border: none;
padding: 15px 32px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 16px;
margin: 4px 2px;
cursor: pointer;
border-radius: 5px;
}
</style>

View File

@ -1,6 +1,6 @@
<script setup>
import axios from 'axios';
import { onMounted, ref } from "vue";
import { onMounted, ref, computed } from "vue";
import { useRoute } from "vue-router";
import NavbarDefault from '../../../examples/navbars/NavbarDefault.vue';
@ -9,6 +9,11 @@ const projectId = ref(null);
const route = useRoute();
const projectData = ref([]);
const isAuthenticated = computed(() => !!sessionStorage.getItem('access_token'));
const userId = computed(() => sessionStorage.getItem('user_id'));
const loggedUserName = computed(() => sessionStorage.getItem('username'));
const token = computed(() => sessionStorage.getItem('access_token'));
onMounted(async() => {
projectId.value = route.params.id;
await getProject();
@ -32,27 +37,88 @@ const getProject = async () => {
<template>
<NavbarDefault />
<div v-if="projectData">
<h1>Проект номер: {{ projectData.id }}</h1>
<h2>{{ projectData.title }}</h2>
<p>{{ projectData.description }}</p>
<img :src="projectData.featured_image" alt="Featured image">
<p v-if="projectData.demo_link">Demo Link: <a :href="projectData.demo_link">{{ projectData.demo_link }}</a></p>
<p v-if="projectData.source_link">Source Link: <a :href="projectData.source_link">{{ projectData.source_link }}</a></p>
<p>Total Votes: {{ projectData.vote_total }}</p>
<p>Vote Ratio: {{ projectData.vote_ratio }}</p>
<p>Created On: {{ new Date(projectData.created).toLocaleDateString() }}</p>
<p>Owner ID: {{ projectData.owner }}</p>
<p>Tags:
<span v-for="(tag, index) in projectData.tags" :key="index">
<div v-if="projectData" class="project-container">
<h1 class="project-title">Проект номер: {{ projectData.id }}</h1>
<h2 class="project-subtitle">{{ projectData.title }}</h2>
<div v-if = "projectData.owner == userId" class="project-owner-note">
<a :href="`/editproject/${projectData.id}`">Редактирование проекта</a>
</div>
<p class="project-description">{{ projectData.description }}</p>
<img class="project-image" :src="projectData.featured_image" alt="Featured image">
<p v-if="projectData.demo_link" class="project-demo-link">Demo Link: <a :href="projectData.demo_link">{{ projectData.demo_link }}</a></p>
<p v-if="projectData.source_link" class="project-source-link">Source Link: <a :href="projectData.source_link">{{ projectData.source_link }}</a></p>
<p class="project-votes">Total Votes: {{ projectData.vote_total }}</p>
<p class="project-vote-ratio">Vote Ratio: {{ projectData.vote_ratio }}</p>
<p class="project-created">Created On: {{ new Date(projectData.created).toLocaleDateString() }}</p>
<p class="project-owner-id">Owner ID: {{ projectData.owner }}</p>
<p class="project-tags">Tags:
<span v-for="(tag, index) in projectData.tags" :key="index" class="project-tag">
{{ tag }}<span v-if="index < projectData.tags.length - 1">, </span>
</span>
</p>
</div>
</template>
</template>
<style scoped>
.project-container {
margin: 20px;
padding: 20px;
border: 1px solid #ddd;
border-radius: 5px;
background-color: #f9f9f9;
}
.project-title {
font-size: 24px;
font-weight: bold;
color: #333;
}
.project-subtitle {
font-size: 18px;
color: #555;
}
.project-owner-note {
font-size: 16px;
color: #777;
margin-bottom: 20px;
}
.project-description {
font-size: 16px;
color: #333;
margin-bottom: 20px;
}
.project-image {
width: 100%;
height: auto;
margin-bottom: 20px;
}
.project-demo-link, .project-source-link {
font-size: 16px;
color: #337ab7;
text-decoration: none;
}
.project-votes, .project-vote-ratio, .project-created, .project-owner-id {
font-size: 14px;
color: #777;
}
.project-tags {
font-size: 14px;
color: #333;
}
.project-tag {
background-color: #f0f0f0;
border-radius: 5px;
padding: 2px 5px;
margin: 2px;
}
</style>

View File

@ -15,9 +15,11 @@ const username = ref('');
const password = ref('');
const errorMessage = ref('');
const isAuthenticated = computed(() => !!sessionStorage.getItem('access_token')); // Computed property to check if the user is authenticated
//Это блок для работы с хранилищем сессии
const isAuthenticated = computed(() => !!sessionStorage.getItem('access_token'));
const userId = computed(() => sessionStorage.getItem('user_id'));
const loggedUserName = computed(() => sessionStorage.getItem('username'));
const isStaff = computed(() => sessionStorage.getItem('is_staff'));
const login = async () => {
if (!username.value || !password.value) {
@ -36,8 +38,9 @@ const login = async () => {
const response = await axios.post(url, body, { headers });
// Removed debug information from output
sessionStorage.setItem('access_token', response.data.access);
sessionStorage.setItem('username', username.value); // Save username in sessionStorage
sessionStorage.setItem('user_id', response.data.id); // Save the user id in sessionStorage
sessionStorage.setItem('username', username.value);
sessionStorage.setItem('user_id', response.data.id);
sessionStorage.setItem('is_staff', response.data.is_staff);
location.reload(); // Refresh page
} catch (error) {
if (error.response) {
@ -55,6 +58,7 @@ const logout = () => {
sessionStorage.removeItem('access_token');
sessionStorage.removeItem('username'); // Also clear the username from sessionStorage
sessionStorage.removeItem('user_id');
sessionStorage.setItem('is_staff', false);
location.reload(); // Refresh page after logout
};
@ -120,7 +124,16 @@ export default {
<div>
<div v-if="isAuthenticated">
<!-- This will only be displayed if the user is authenticated -->
<p>Вы вошли в аккаунт {{ loggedUserName }}, ваш ID {{ userId }}</p>
<p>Вы вошли в аккаунт {{ loggedUserName }}</p>
<p>
<a href="/ViewMyProfile">Перейти в профиль.</a>
</p>
<!-- Это должно быть видно только админам -->
<div v-if="isStaff">
<p>
<a href="/admin">Перейти в панель администратора.</a>
</p>
</div>
<button @click="logout">Выход</button>
</div>
@ -128,9 +141,6 @@ export default {
<!-- This will be displayed if the user is not authenticated -->
<p>Пожалуйста, введите логин и пароль</p>
<div>
<input v-model="username" type="text" placeholder="Имя пользователя" />
</div>
@ -151,16 +161,7 @@ export default {
</div>
</div>
<div v-if="errorMessage">
<p>{{ errorMessage }}</p>
</div>
</div>
<p class="mt-4 text-sm text-center">
<p class="mt-4 text-sm text-center">
Нет аккаунта?
<a
href="/register"
@ -170,12 +171,24 @@ export default {
</p>
<p class="mt-4 text-sm text-center">
<a
href="/forgot"
class="text-success text-gradient font-weight-bold"
>Забыли пароль</a
>
</p>
<a
href="/forgot"
class="text-success text-gradient font-weight-bold"
>Забыли пароль</a
>
</p>
</div>
<div v-if="errorMessage">
<p>{{ errorMessage }}</p>
</div>
</div>
</form>
</div>
</div>