Commit 7871a959 by asranov0003

feat: render notification list

parent 7fd1cc7d
...@@ -33,6 +33,10 @@ ...@@ -33,6 +33,10 @@
"verified": "Verified", "verified": "Verified",
"unVerified": "Unverified" "unVerified": "Unverified"
}, },
"notification": {
"title": "Notifications",
"empty": "No notifications"
},
"pincode": { "pincode": {
"enterTitle": "Enter your PIN Code", "enterTitle": "Enter your PIN Code",
"createTitle": "Create your PIN Code", "createTitle": "Create your PIN Code",
......
...@@ -33,6 +33,10 @@ ...@@ -33,6 +33,10 @@
"verified": "Подтверждено", "verified": "Подтверждено",
"unVerified": "Не подтверждено" "unVerified": "Не подтверждено"
}, },
"notification": {
"title": "Уведомления",
"empty": "Нет уведомлений"
},
"pincode": { "pincode": {
"enterTitle": "Введите PIN-код", "enterTitle": "Введите PIN-код",
"createTitle": "Создайте PIN-код", "createTitle": "Создайте PIN-код",
......
.home {
padding: 0 1rem;
}
\ No newline at end of file
...@@ -2,7 +2,7 @@ import React from "react"; ...@@ -2,7 +2,7 @@ import React from "react";
import "./Home.css"; import "./Home.css";
const Home: React.FC = () => { const Home: React.FC = () => {
return <div>Home</div>; return <div className="home">Home</div>;
}; };
export default Home; export default Home;
.notifications {
padding: 0 1rem;
}
.notification__title {
margin-bottom: 1rem;
}
.notifications__list {
display: flex;
flex-direction: column;
gap: 1rem;
}
.notification {
padding: 1rem;
background: #ffffff;
border-radius: 0.5rem;
}
.notification__caption {
font-weight: bold;
display: flex;
align-items: center;
gap: 0.5rem;
}
.notification__caption__icon {
font-size: 1.5rem;
color: var(--danger-color);
}
.notification__text {
font-size: 0.875rem;
margin: 0.5rem 0;
white-space: pre-wrap;
word-break: break-word;
overflow-wrap: anywhere;
}
.notification__date {
display: flex;
justify-content: space-between;
font-size: 0.875rem;
color: var(--gray-color);
}
.notification__date__icon {
font-size: 1.2rem;
color: var(--primary-color);
}
\ No newline at end of file
import React from "react"; import React, { useEffect } from "react";
import "./Notifications.css"; import "./Notifications.css";
import {
useAppDispatch,
useAppSelector,
type RootState,
} from "../../stores/store";
import { getList } from "../../stores/slices/notificationSlice";
import { MdBlockFlipped } from "react-icons/md";
import { IoPhonePortraitOutline } from "react-icons/io5";
import { useTranslation } from "react-i18next";
const Notifications: React.FC = () => { const Notifications: React.FC = () => {
return <div>Notifications</div>; const { t } = useTranslation();
const dispatch = useAppDispatch();
const getDefaultDates = () => {
const dateTo = new Date();
const dateFrom = new Date(dateTo);
dateFrom.setDate(dateTo.getDate() - 30);
return { dateFrom, dateTo };
};
const { notifications } = useAppSelector(
(state: RootState) => state.notification
);
useEffect(() => {
dispatch(getList(getDefaultDates()));
}, [dispatch]);
return (
<div className="notifications">
<h3 className="notification__title">{t("notification.title")}</h3>
<div className="notifications__list">
{notifications.length > 0 ? (
notifications.map((notification) => (
<div className="notification" key={notification.id}>
<div className="notification__caption">
<MdBlockFlipped className="notification__caption__icon" />
<p>{notification.caption}</p>
</div>
<p className="notification__text">{notification.text}</p>
<div className="notification__date">
<IoPhonePortraitOutline className="notification__date__icon" />
{new Date(notification.date).toLocaleString()}
</div>
</div>
))
) : (
<p>{t("notification.empty")}</p>
)}
</div>
</div>
);
}; };
export default Notifications; export default Notifications;
.settings {
padding: 0 1rem;
}
\ No newline at end of file
...@@ -2,7 +2,7 @@ import React from "react"; ...@@ -2,7 +2,7 @@ import React from "react";
import "./Settings.css"; import "./Settings.css";
const Settings: React.FC = () => { const Settings: React.FC = () => {
return <div>Settings</div>; return <div className="settings">Settings</div>;
}; };
export default Settings; export default Settings;
.subscription {
padding: 0 1rem;
}
\ No newline at end of file
...@@ -2,7 +2,7 @@ import React from "react"; ...@@ -2,7 +2,7 @@ import React from "react";
import "./Subscription.css"; import "./Subscription.css";
const Subscription: React.FC = () => { const Subscription: React.FC = () => {
return <div>Subscription</div>; return <div className="subscription">Subscription</div>;
}; };
export default Subscription; export default Subscription;
import { createAsyncThunk, createSlice } from "@reduxjs/toolkit";
import { sendRpcRequest } from "../../services/apiClient";
interface INotification {
id: string;
caption: string;
text: string;
action: string;
date: string;
deviceId: string;
type: string;
}
interface INotificationState {
notifications: INotification[];
loading: boolean;
}
const initialState: INotificationState = {
notifications: [],
loading: false,
};
export const getList = createAsyncThunk(
"notifications/fetch",
async (
{ dateFrom, dateTo }: { dateFrom: Date; dateTo: Date },
{ rejectWithValue }
) => {
try {
const response = await sendRpcRequest<{ list: INotification[] }>(
"notif.getList",
{
dateFrom,
dateTo,
recStart: 0,
recLimit: 30,
}
);
return response.list;
} catch (error: unknown) {
if (typeof error === "object" && error !== null && "message" in error) {
return rejectWithValue(error.message);
}
return rejectWithValue("Unknown error occurred");
}
}
);
const notificationSlice = createSlice({
name: "notifications",
initialState,
reducers: {},
extraReducers: (builder) => {
builder
.addCase(getList.pending, (state) => {
state.loading = true;
})
.addCase(getList.fulfilled, (state, action) => {
state.loading = false;
state.notifications = action.payload;
})
.addCase(getList.rejected, (state) => {
state.loading = false;
});
},
});
export default notificationSlice.reducer;
import { configureStore } from "@reduxjs/toolkit"; import { configureStore } from "@reduxjs/toolkit";
import authSlice from "./slices/authSlice"; import authSlice from "./slices/authSlice";
import accountSlice from "./slices/accountSlice"; import accountSlice from "./slices/accountSlice";
import notificationSlice from "./slices/notificationSlice";
import { import {
useDispatch, useDispatch,
useSelector, useSelector,
...@@ -11,6 +12,7 @@ export const store = configureStore({ ...@@ -11,6 +12,7 @@ export const store = configureStore({
reducer: { reducer: {
auth: authSlice, auth: authSlice,
account: accountSlice, account: accountSlice,
notification: notificationSlice,
}, },
}); });
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment