Skip to content

Commit

Permalink
Fix local yandex (#154)
Browse files Browse the repository at this point in the history
* fix bug with localStorage accessToken extra quotes

* fix localStorage issue, but logout in Yandex doesnt work

---------

Co-authored-by: Daniil <daniilminin1990@yandex.ru>
  • Loading branch information
momecaptr and daniilminin1990 authored Dec 8, 2024
1 parent 2dc4d50 commit 00ac624
Show file tree
Hide file tree
Showing 7 changed files with 185 additions and 38 deletions.
2 changes: 1 addition & 1 deletion src/entities/userNotifications/UserNotifications.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ const SOCKET_URL = 'https://inctagram.work';
const START_NOTICES_COUNT = 5;

const UserNotifications = () => {
const ACCESS_TOKEN = JSON.parse(localStorage.getItem('accessToken') as string);
const ACCESS_TOKEN = localStorage.getItem('accessToken');
const socketRef = useRef<Socket | null>(null);
const dispatch = useAppDispatch();

Expand Down
6 changes: 3 additions & 3 deletions src/entities/userNotifications/api/notificationSlice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export const fetchNotifications = createAsyncThunk(
async (args: NotificationsArgs, ThunkAPI) => {
const { rejectWithValue } = ThunkAPI;
const { cursor = null, pageSize, sortBy = 'notifyAt', sortDirection = 'desc' } = args;
const ACCESS_TOKEN = JSON.parse(localStorage.getItem('accessToken') as string);
const ACCESS_TOKEN = localStorage.getItem('accessToken');

try {
const response = await axios.get<NotificationsResponse>(
Expand All @@ -55,7 +55,7 @@ export const fetchNotifications = createAsyncThunk(
export const markNotificationsAsRead = createAsyncThunk(
'notifications/markAsRead',
async (ids: number[], { rejectWithValue }) => {
const ACCESS_TOKEN = JSON.parse(localStorage.getItem('accessToken') as string);
const ACCESS_TOKEN = localStorage.getItem('accessToken');

try {
await axios.put(
Expand All @@ -77,7 +77,7 @@ export const markNotificationsAsRead = createAsyncThunk(
export const deleteNotification = createAsyncThunk(
'notifications/deleteNotification',
async (id: number, { rejectWithValue }) => {
const ACCESS_TOKEN = JSON.parse(localStorage.getItem('accessToken') as string);
const ACCESS_TOKEN = localStorage.getItem('accessToken');

try {
await axios.delete(`https://inctagram.work/api/v1/notifications/${id}`, {
Expand Down
177 changes: 177 additions & 0 deletions src/entities/userNotifications/api/notificationSlice.ts~
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
import {
INotificationItem,
NotificationsArgs,
NotificationsResponse
} from '@/shared/api/notifications/notificationsTypes';
import { PayloadAction, createAsyncThunk, createSlice } from '@reduxjs/toolkit';
import axios from 'axios';

interface NotificationsState {
cursorId: null | number;
error: null | string;
isFetching: boolean;
isOpen: boolean;
notReadCount: number;
notifications: INotificationItem[];
totalCount: number;
}

const initialState: NotificationsState = {
cursorId: null,
error: null,
isFetching: false,
isOpen: false,
notReadCount: 0,
notifications: [],
totalCount: 0
};

// Thunk для загрузки уведомлений
export const fetchNotifications = createAsyncThunk(
'notifications/fetchNotifications',
async (args: NotificationsArgs, ThunkAPI) => {
const { rejectWithValue } = ThunkAPI;
const { cursor = null, pageSize, sortBy = 'notifyAt', sortDirection = 'desc' } = args;
const ACCESS_TOKEN = JSON.parse(localStorage.getItem('accessToken') as string);

try {
const response = await axios.get<NotificationsResponse>(
`https://inctagram.work/api/v1/notifications/${cursor}?pageSize=${pageSize}&sortBy=${sortBy}&sortDirection=${sortDirection}`,
{
headers: {
Authorization: `Bearer ${ACCESS_TOKEN}`
}
}
);

return response.data;
} catch (error: any) {
return rejectWithValue(error.message);
}
}
);

// Thunk для отметки уведомлений как прочитанных
export const markNotificationsAsRead = createAsyncThunk(
'notifications/markAsRead',
async (ids: number[], { rejectWithValue }) => {
const ACCESS_TOKEN = JSON.parse(localStorage.getItem('accessToken') as string);

try {
await axios.put(
'https://inctagram.work/api/v1/notifications/mark-as-read',
{ ids },
{
headers: {
Authorization: `Bearer ${ACCESS_TOKEN}`
}
}
);
} catch (error: any) {
return rejectWithValue(error.message);
}
}
);

// Thunk для удаления уведомления
export const deleteNotification = createAsyncThunk(
'notifications/deleteNotification',
async (id: number, { rejectWithValue }) => {
const ACCESS_TOKEN = JSON.parse(localStorage.getItem('accessToken') as string);

try {
await axios.delete(`https://inctagram.work/api/v1/notifications/${id}`, {
headers: {
Authorization: `Bearer ${ACCESS_TOKEN}`
}
});
} catch (error: any) {
return rejectWithValue(error.message);
}
}
);

const slice = createSlice({
extraReducers: (builder) => {
builder
.addCase(fetchNotifications.pending, (state) => {
state.isFetching = true;
})
.addCase(fetchNotifications.fulfilled, (state, action) => {
const existingIds = new Set(state.notifications.map((notice) => notice.id));
const newNotifications = action.payload.items.filter((item) => !existingIds.has(item.id));

state.notifications = [...state.notifications, ...newNotifications];

/*state.notifications = [...state.notifications, ...action.payload.items];*/
state.totalCount = action.payload.totalCount;
state.isFetching = false;
state.cursorId = action.payload.items[action.payload.items.length - 1]?.id;

state.notReadCount = action.payload.notReadCount;
})
.addCase(fetchNotifications.rejected, (state, action) => {
state.isFetching = false;
state.error = action.payload as string;
})
.addCase(deleteNotification.pending, (state) => {
state.isFetching = true;
})
.addCase(deleteNotification.fulfilled, (state, action) => {
state.isFetching = false;
state.notifications = state.notifications.filter((notification) => notification.id !== action.meta.arg);
state.totalCount -= 1;
})
.addCase(deleteNotification.rejected, (state, action) => {
state.error = action.payload as string;
state.isFetching = false;
})
.addCase(markNotificationsAsRead.pending, (state) => {
state.isFetching = true;
})
.addCase(markNotificationsAsRead.fulfilled, (state, action) => {
state.isFetching = false;
const readIds = new Set(action.meta.arg);

// Создаем новый массив с обновленными уведомлениями
const updatedNotifications = state.notifications.map((notification) => {
if (readIds.has(notification.id)) {
return { ...notification, isRead: true };
}

return notification;
});

// Обновляем состояние с новым массивом уведомлений
state.notifications = updatedNotifications;
state.notReadCount -= readIds.size;
})
.addCase(markNotificationsAsRead.rejected, (state, action) => {
state.error = action.payload as string;
state.isFetching = false;
});
},
initialState: initialState,
name: 'notifications',
reducers: {
addNewNotification: (state, action: PayloadAction<INotificationItem>) => {
state.notifications.unshift(action.payload);
},
changeDropDownState: (state, action: PayloadAction<{ isOpen: boolean }>) => {
state.isOpen = action.payload.isOpen;
}
},
selectors: {
getCursorId: (state) => state.cursorId,
getHasMore: (state) => state.notifications.length < state.totalCount,
getIsFetching: (state) => state.isFetching,
getIsOpen: (state) => state.isOpen,
getNotReadCount: (state) => state.notReadCount,
getNotifications: (state) => state.notifications,
getTotalCount: (state) => state.totalCount
}
});

export const notificationActions = slice.actions;
export const notificationSlice = slice.reducer;
export const notificationSelectors = slice.selectors;
2 changes: 1 addition & 1 deletion src/features/googleButton/lib/useAuthGoogle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export const useAuthGoogle = () => {
const resGoogleOAuth = await authMeGoogle({ code: codeResponse.code });
const accessToken = resGoogleOAuth.data?.accessToken;

localStorage.setItem('accessToken', JSON.stringify(accessToken));
localStorage.setItem('accessToken', String(accessToken));
// Расшифровываем токен и получаем данные пользователя
const decodedToken = jwtDecode<{ userId: string }>(accessToken ? accessToken : '');

Expand Down
3 changes: 1 addition & 2 deletions src/shared/api/auth/authApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,7 @@ export const authApi = snapmomentAPI.injectEndpoints({
localStorage.removeItem('accessToken');
dispatch(authApi.util.resetApiState());
},
query: (body) => ({
body,
query: () => ({
method: 'POST',
url: 'v1/auth/logout'
})
Expand Down
6 changes: 2 additions & 4 deletions src/shared/api/common/snapmomentBaseQuery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,14 @@ const baseQuery = fetchBaseQuery({
credentials: 'include',
prepareHeaders: (headers) => {
const token = (typeof window !== 'undefined' && localStorage.getItem('accessToken')) || null;
const parsedToken = token ? JSON.parse(token) : null;

if (headers.get('Authorization')) {
return headers;
}

if (token) {
headers.set('Authorization', `Bearer ${parsedToken}`);
headers.set('Authorization', `Bearer ${token}`);
}
// headers.set('Authorization', `Bearer ${token}`);

return headers;
}
Expand Down Expand Up @@ -50,7 +48,7 @@ export const baseQueryWithReauth: BaseQueryFn<FetchArgs | string, unknown, Fetch
const refreshResultParsed = RefreshTokenResponseSchema.parse(refreshResult.data);

if (refreshResult.meta.response.status === 200) {
localStorage.setItem('accessToken', refreshResultParsed.accessToken);
localStorage.setItem('accessToken', refreshResult.data.accessToken);
result = await baseQuery(args, api, extraOptions);
}
}
Expand Down
27 changes: 0 additions & 27 deletions src/widget/sideBar/SideBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ type MainLinksProps = {

type LinksValue =
| ''
// | 'create'
| 'favorites'
| 'home'
| 'logout'
Expand Down Expand Up @@ -59,38 +58,13 @@ export const SideBar = (props: Props) => {

const mainLinks: MainLinksProps[] = [
{ IconComponent: Home, name: 'Home', path: '/home', value: 'home' },
// { IconComponent: PlusSquare, name: 'Create', path: '/auth/create', value: 'create' },
{ IconComponent: Person, name: 'My Profile', path: `/profile/${me?.userId}`, value: 'profile' },
{ IconComponent: MessageCircle, name: 'Messenger', path: '/message', value: 'message' },
{ IconComponent: SearchOutline, name: 'Search', path: '/search', value: 'search' },
{ IconComponent: TrendingUp, name: 'Statistics', path: '/statistics', value: 'statistics' },
{ IconComponent: Bookmark, name: 'Favorites', path: '/favorites', value: 'favorites' }
];

// const pseudoPromise = () => {
// return new Promise((resolve, reject) => {
// setTimeout(() => {
// const random = Math.random();
//
// if (random > 0.5) {
// resolve('Success data');
// } else {
// reject('Error data');
// }
// }, 1000);
// });
// };
//
// const handleClick = () => {
// const promise = pseudoPromise();
//
// showPromiseToast(promise, {
// error: 'Error occurred',
// loading: 'loading...',
// success: 'Success'
// });
// };

return (
<div className={s.container}>
<CreatePostModal isOpen={isOpen} setOpen={setOpen} />
Expand All @@ -105,7 +79,6 @@ export const SideBar = (props: Props) => {
</Typography>
</Link>
))}
{/*<button onClick={handleClick}>СПИПИП</button>*/}
<Button className={s.btn} onClick={openCreatePostModalHandler} variant={'text'}>
<PlusSquare className={s.icon} />
<Typography as={'span'} className={s.btnText} variant={'medium_text_14'}>
Expand Down

0 comments on commit 00ac624

Please sign in to comment.