Commit 7871a959 by asranov0003

feat: render notification list

parent 7fd1cc7d
......@@ -33,6 +33,10 @@
"verified": "Verified",
"unVerified": "Unverified"
},
"notification": {
"title": "Notifications",
"empty": "No notifications"
},
"pincode": {
"enterTitle": "Enter your PIN Code",
"createTitle": "Create your PIN Code",
......
......@@ -33,6 +33,10 @@
"verified": "Подтверждено",
"unVerified": "Не подтверждено"
},
"notification": {
"title": "Уведомления",
"empty": "Нет уведомлений"
},
"pincode": {
"enterTitle": "Введите PIN-код",
"createTitle": "Создайте PIN-код",
......
.home {
padding: 0 1rem;
}
\ No newline at end of file
......@@ -2,7 +2,7 @@ import React from "react";
import "./Home.css";
const Home: React.FC = () => {
return <div>Home</div>;
return <div className="home">Home</div>;
};
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 {
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 = () => {
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;
.settings {
padding: 0 1rem;
}
\ No newline at end of file
......@@ -2,7 +2,7 @@ import React from "react";
import "./Settings.css";
const Settings: React.FC = () => {
return <div>Settings</div>;
return <div className="settings">Settings</div>;
};
export default Settings;
.subscription {
padding: 0 1rem;
}
\ No newline at end of file
......@@ -2,7 +2,7 @@ import React from "react";
import "./Subscription.css";
const Subscription: React.FC = () => {
return <div>Subscription</div>;
return <div className="subscription">Subscription</div>;
};
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 authSlice from "./slices/authSlice";
import accountSlice from "./slices/accountSlice";
import notificationSlice from "./slices/notificationSlice";
import {
useDispatch,
useSelector,
......@@ -11,6 +12,7 @@ export const store = configureStore({
reducer: {
auth: authSlice,
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