Tons of updates. Rags paginated tables, site tracking
This commit is contained in:
6773
llm-fe/package-lock.json
generated
6773
llm-fe/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -18,6 +18,7 @@
|
|||||||
"bootstrap": "^5.3.3",
|
"bootstrap": "^5.3.3",
|
||||||
"chroma-js": "^3.1.2",
|
"chroma-js": "^3.1.2",
|
||||||
"formik": "^2.4.6",
|
"formik": "^2.4.6",
|
||||||
|
"js-cookie": "^3.0.5",
|
||||||
"jwt-decode": "^4.0.0",
|
"jwt-decode": "^4.0.0",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"markdown-to-jsx": "^7.7.2",
|
"markdown-to-jsx": "^7.7.2",
|
||||||
@@ -65,9 +66,11 @@
|
|||||||
"@types/lodash": "~4.17.13",
|
"@types/lodash": "~4.17.13",
|
||||||
"@types/react": "^18.3.16",
|
"@types/react": "^18.3.16",
|
||||||
"@types/react-dom": "^18.3.5",
|
"@types/react-dom": "^18.3.5",
|
||||||
|
"@types/react-google-recaptcha": "^2.1.9",
|
||||||
"@types/react-syntax-highlighter": "^15.5.13",
|
"@types/react-syntax-highlighter": "^15.5.13",
|
||||||
"react": "^18.3.1",
|
"react": "^18.3.1",
|
||||||
"react-dom": "^18.3.1",
|
"react-dom": "^18.3.1",
|
||||||
|
"react-google-recaptcha": "^3.1.0",
|
||||||
"typescript": "^4.9.5"
|
"typescript": "^4.9.5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,8 +15,10 @@ import FeedbackPage from './llm-fe/pages/FeedbackPage/FeedbackPage';
|
|||||||
import { Typography } from '@mui/material';
|
import { Typography } from '@mui/material';
|
||||||
import AsyncDashboard2 from './llm-fe/pages/AsyncDashboard2/AsyncDashboard2';
|
import AsyncDashboard2 from './llm-fe/pages/AsyncDashboard2/AsyncDashboard2';
|
||||||
import FeedbackPage2 from './llm-fe/pages/FeedbackPage2/FeedbackPage2';
|
import FeedbackPage2 from './llm-fe/pages/FeedbackPage2/FeedbackPage2';
|
||||||
|
import DocumentStoragePage from './llm-fe/pages/DocumentStoragePage/DocumentStoragePage';
|
||||||
import Account2 from './llm-fe/pages/Account2/Account2';
|
import Account2 from './llm-fe/pages/Account2/Account2';
|
||||||
import AnalyticsPage from './llm-fe/pages/Analytics/Analytics';
|
import AnalyticsPage from './llm-fe/pages/Analytics/Analytics';
|
||||||
|
import PasswordResetConfirmation from './llm-fe/pages/PasswordResetConfirmation/PasswordReset';
|
||||||
|
|
||||||
const ProtectedRoutes = () => {
|
const ProtectedRoutes = () => {
|
||||||
const { authenticated, needsNewPassword, loading } = useContext(AuthContext);
|
const { authenticated, needsNewPassword, loading } = useContext(AuthContext);
|
||||||
@@ -45,6 +47,7 @@ class App extends Component {
|
|||||||
|
|
||||||
<Route path={"/signin/"} Component={SignIn}/>
|
<Route path={"/signin/"} Component={SignIn}/>
|
||||||
<Route path={"/password_reset/"} Component={PasswordReset}/>
|
<Route path={"/password_reset/"} Component={PasswordReset}/>
|
||||||
|
<Route path={"/password_reset_confirmation/"} Component={PasswordResetConfirmation}/>
|
||||||
<Route path={'/set_password/'} Component={SetPassword}/>
|
<Route path={'/set_password/'} Component={SetPassword}/>
|
||||||
|
|
||||||
|
|
||||||
@@ -52,6 +55,7 @@ class App extends Component {
|
|||||||
<Route element={<ProtectedRoutes />}>
|
<Route element={<ProtectedRoutes />}>
|
||||||
<Route path={"/"} index={true} Component={AsyncDashboard2}/>
|
<Route path={"/"} index={true} Component={AsyncDashboard2}/>
|
||||||
<Route path={"/account/"} Component={Account2}/>
|
<Route path={"/account/"} Component={Account2}/>
|
||||||
|
<Route path={"/document_storage"} Component={DocumentStoragePage}/>
|
||||||
<Route path={"/terms_of_service/"} Component={TermsOfService}/>
|
<Route path={"/terms_of_service/"} Component={TermsOfService}/>
|
||||||
<Route path={"/feedback/"} Component={FeedbackPage2}/>
|
<Route path={"/feedback/"} Component={FeedbackPage2}/>
|
||||||
<Route path={"/analytics/"} Component={AnalyticsPage} />
|
<Route path={"/analytics/"} Component={AnalyticsPage} />
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
|
const Cookies = require('js-cookie');
|
||||||
|
|
||||||
//const baseURL = 'http://127.0.0.1:8001/api/';
|
//const baseURL = 'http://127.0.0.1:8011/api/';
|
||||||
const baseURL = 'https://chatbackend.aimloperations.com/api/';
|
const baseURL = 'https://chatbackend.aimloperations.com/api/';
|
||||||
//const baseURL = process.env.REACT_APP_BACKEND_REST_API_BASE_URL;
|
//const baseURL = process.env.REACT_APP_BACKEND_REST_API_BASE_URL;
|
||||||
|
|
||||||
@@ -14,6 +15,25 @@ export const axiosInstance = axios.create({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const cleanAxiosInstance = axios.create({
|
||||||
|
baseURL: baseURL,
|
||||||
|
timeout: 5000,
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'Accept': 'application/json',
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
export const axiosInstanceCSRF = axios.create({
|
||||||
|
baseURL: baseURL,
|
||||||
|
timeout: 5000,
|
||||||
|
headers: {
|
||||||
|
'X-CSRFToken': Cookies.get('csrftoken'), // Include CSRF token in headers
|
||||||
|
},
|
||||||
|
withCredentials: true,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
axiosInstance.interceptors.request.use(config => {
|
axiosInstance.interceptors.request.use(config => {
|
||||||
config.timeout = 100000;
|
config.timeout = 100000;
|
||||||
return config;
|
return config;
|
||||||
|
|||||||
@@ -47,6 +47,10 @@ const Header2 = ({ absolute=false, light=false, isMini=false }: Header2Props): J
|
|||||||
const handleDashboardClick = async () => {
|
const handleDashboardClick = async () => {
|
||||||
navigate('/')
|
navigate('/')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const handleDocumentStorageClick = async () => {
|
||||||
|
navigate('/document_storage/')
|
||||||
|
}
|
||||||
|
|
||||||
const handleAccountClick = async () => {
|
const handleAccountClick = async () => {
|
||||||
navigate('/account/')
|
navigate('/account/')
|
||||||
@@ -76,6 +80,8 @@ const Header2 = ({ absolute=false, light=false, isMini=false }: Header2Props): J
|
|||||||
</MDBox>
|
</MDBox>
|
||||||
<MDBox sx={{marginLeft: "auto"}}>
|
<MDBox sx={{marginLeft: "auto"}}>
|
||||||
<Button color="inherit" onClick={handleAccountClick}>Account</Button>
|
<Button color="inherit" onClick={handleAccountClick}>Account</Button>
|
||||||
|
|
||||||
|
<Button color="inherit" onClick={handleDocumentStorageClick}>Document Storage</Button>
|
||||||
|
|
||||||
<Button color="inherit" onClick={handleAnalyticsClick}>Analytics</Button>
|
<Button color="inherit" onClick={handleAnalyticsClick}>Analytics</Button>
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,93 @@
|
|||||||
|
import React, { useState } from 'react';
|
||||||
|
import {
|
||||||
|
Table,
|
||||||
|
TableBody,
|
||||||
|
TableCell,
|
||||||
|
TableContainer,
|
||||||
|
TableHead,
|
||||||
|
TableRow,
|
||||||
|
Paper,
|
||||||
|
TablePagination,
|
||||||
|
} from "@mui/material";;
|
||||||
|
|
||||||
|
interface PaginatedTableProps<T> {
|
||||||
|
data: T[];
|
||||||
|
columns: {
|
||||||
|
key: keyof T;
|
||||||
|
label: string;
|
||||||
|
render?: (value: any, row: T) => React.ReactNode;
|
||||||
|
}[];
|
||||||
|
rowsPerPageOptions?: number[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export function PaginatedTable<T>({
|
||||||
|
data,
|
||||||
|
columns,
|
||||||
|
rowsPerPageOptions = [5, 10, 25],
|
||||||
|
}: PaginatedTableProps<T>) {
|
||||||
|
const [page, setPage] = useState(0);
|
||||||
|
const [rowsPerPage, setRowsPerPage] = useState(rowsPerPageOptions[0]);
|
||||||
|
|
||||||
|
const handleChangePage = (event: unknown, newPage: number) => {
|
||||||
|
setPage(newPage);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleChangeRowsPerPage = (
|
||||||
|
event: React.ChangeEvent<HTMLInputElement>
|
||||||
|
) => {
|
||||||
|
setRowsPerPage(parseInt(event.target.value, 10));
|
||||||
|
setPage(0);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Avoid a layout jump when reaching the last page with empty rows.
|
||||||
|
const emptyRows =
|
||||||
|
page > 0 ? Math.max(0, (1 + page) * rowsPerPage - data.length) : 0;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Paper>
|
||||||
|
<TableContainer>
|
||||||
|
<Table>
|
||||||
|
<TableHead>
|
||||||
|
<TableRow>
|
||||||
|
{columns.map((column) => (
|
||||||
|
<TableCell key={column.key.toString()}>{column.label}</TableCell>
|
||||||
|
))}
|
||||||
|
</TableRow>
|
||||||
|
</TableHead>
|
||||||
|
<TableBody>
|
||||||
|
{(rowsPerPage > 0
|
||||||
|
? data.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage)
|
||||||
|
: data
|
||||||
|
).map((row, index) => (
|
||||||
|
<TableRow key={index}>
|
||||||
|
{columns.map((column) => (
|
||||||
|
<TableCell key={column.key.toString()}>
|
||||||
|
{column.render
|
||||||
|
? column.render(row[column.key], row)
|
||||||
|
: (row[column.key] as React.ReactNode)}
|
||||||
|
</TableCell>
|
||||||
|
))}
|
||||||
|
</TableRow>
|
||||||
|
))}
|
||||||
|
{emptyRows > 0 && (
|
||||||
|
<TableRow style={{ height: 53 * emptyRows }}>
|
||||||
|
<TableCell colSpan={columns.length} />
|
||||||
|
</TableRow>
|
||||||
|
)}
|
||||||
|
</TableBody>
|
||||||
|
</Table>
|
||||||
|
</TableContainer>
|
||||||
|
<TablePagination
|
||||||
|
rowsPerPageOptions={rowsPerPageOptions}
|
||||||
|
component="div"
|
||||||
|
count={data.length}
|
||||||
|
rowsPerPage={rowsPerPage}
|
||||||
|
page={page}
|
||||||
|
onPageChange={handleChangePage}
|
||||||
|
onRowsPerPageChange={handleChangeRowsPerPage}
|
||||||
|
/>
|
||||||
|
</Paper>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default PaginatedTable;
|
||||||
@@ -24,7 +24,7 @@ function WebSocketProvider({ children }) {
|
|||||||
delete channels.current[channel]
|
delete channels.current[channel]
|
||||||
}
|
}
|
||||||
|
|
||||||
const sendMessage = (message, conversation_id, file, fileType) => {
|
const sendMessage = (message, conversation_id, file, fileType, modelName) => {
|
||||||
if (socket && socket.readyState === WebSocket.OPEN){
|
if (socket && socket.readyState === WebSocket.OPEN){
|
||||||
|
|
||||||
if (file){
|
if (file){
|
||||||
@@ -40,6 +40,7 @@ function WebSocketProvider({ children }) {
|
|||||||
email: account?.email,
|
email: account?.email,
|
||||||
file: base64File,
|
file: base64File,
|
||||||
fileType: fileType,
|
fileType: fileType,
|
||||||
|
modelName: modelName,
|
||||||
}
|
}
|
||||||
socket.send(JSON.stringify(data))
|
socket.send(JSON.stringify(data))
|
||||||
|
|
||||||
@@ -52,7 +53,8 @@ function WebSocketProvider({ children }) {
|
|||||||
conversation_id: conversation_id,
|
conversation_id: conversation_id,
|
||||||
email: account?.email,
|
email: account?.email,
|
||||||
file: null,
|
file: null,
|
||||||
fileType: null
|
fileType: null,
|
||||||
|
modelName: modelName,
|
||||||
}
|
}
|
||||||
|
|
||||||
socket.send(JSON.stringify(data))
|
socket.send(JSON.stringify(data))
|
||||||
@@ -69,7 +71,7 @@ function WebSocketProvider({ children }) {
|
|||||||
if (account){
|
if (account){
|
||||||
|
|
||||||
|
|
||||||
//ws.current = new WebSocket(`ws://127.0.0.1:8001/ws/chat_again/`);
|
//ws.current = new WebSocket(`ws://127.0.0.1:8011/ws/chat_again/`);
|
||||||
ws.current = new WebSocket('wss://chatbackend.aimloperations.com/ws/chat_again/')
|
ws.current = new WebSocket('wss://chatbackend.aimloperations.com/ws/chat_again/')
|
||||||
//ws.current = process.env.REACT_APP_BACKEND_WS_API_BASE_URL;
|
//ws.current = process.env.REACT_APP_BACKEND_WS_API_BASE_URL;
|
||||||
|
|
||||||
|
|||||||
@@ -87,6 +87,16 @@ export class Announcement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface DocumentType {
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
|
date_uploaded: string;
|
||||||
|
created: string;
|
||||||
|
file: string;
|
||||||
|
active: boolean;
|
||||||
|
processed: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
export interface FeedbackType {
|
export interface FeedbackType {
|
||||||
id: number;
|
id: number;
|
||||||
title: string;
|
title: string;
|
||||||
@@ -95,7 +105,24 @@ export interface FeedbackType {
|
|||||||
category: string;
|
category: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class Document {
|
||||||
|
id: number = 0;
|
||||||
|
name: string = '';
|
||||||
|
file: string = '';
|
||||||
|
date_uploaded: string = '';
|
||||||
|
active: boolean = false;
|
||||||
|
processed: boolean = false;
|
||||||
|
constructor(initializer?: any){
|
||||||
|
if(!initializer) return;
|
||||||
|
if (initializer.id) this.id = initializer.id;
|
||||||
|
if (initializer.name) this.name = initializer.name;
|
||||||
|
if (initializer.file) this.file = initializer.file;
|
||||||
|
if (initializer.active) this.active = initializer.active;
|
||||||
|
if (initializer.date_uploaded) this.date_uploaded = initializer.date_uploaded;
|
||||||
|
if (initializer.processed) this.processed = initializer.processed;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export class Feedback {
|
export class Feedback {
|
||||||
id: number = 0;
|
id: number = 0;
|
||||||
@@ -238,4 +265,4 @@ export class Account {
|
|||||||
if (initializer.company) this.company = initializer.company;
|
if (initializer.company) this.company = initializer.company;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Card, CardContent, Divider, InputAdornment, } from "@mui/material"
|
import { Card, CardContent, Divider, InputAdornment, MenuItem, Select, } from "@mui/material"
|
||||||
|
|
||||||
import DashboardLayout from "../../ui-kit/examples/LayoutContainers/DashboardLayout"
|
import DashboardLayout from "../../ui-kit/examples/LayoutContainers/DashboardLayout"
|
||||||
|
|
||||||
@@ -29,6 +29,8 @@ import Footer from "../../components/Footer/Footer"
|
|||||||
import { MessageContext } from "../../contexts/MessageContext"
|
import { MessageContext } from "../../contexts/MessageContext"
|
||||||
import CustomSelect, { CustomSelectItem } from "../../components/CustomSelect/CustomSelect"
|
import CustomSelect, { CustomSelectItem } from "../../components/CustomSelect/CustomSelect"
|
||||||
|
|
||||||
|
const MODELS = ["Turbo","RAG"]
|
||||||
|
|
||||||
type RenderMessageProps= {
|
type RenderMessageProps= {
|
||||||
response: string
|
response: string
|
||||||
index: number
|
index: number
|
||||||
@@ -126,7 +128,6 @@ const AsyncDashboardInner =({}): JSX.Element => {
|
|||||||
const handlePromptSubmit = async ({prompt, file, fileType, modelName}: PromptValues, {resetForm}: any): Promise<void> => {
|
const handlePromptSubmit = async ({prompt, file, fileType, modelName}: PromptValues, {resetForm}: any): Promise<void> => {
|
||||||
|
|
||||||
// send the prompt to be saved
|
// send the prompt to be saved
|
||||||
|
|
||||||
try{
|
try{
|
||||||
const tempConversations: ConversationPrompt[] = [...conversationDetails, new ConversationPrompt({message: prompt, user_created:true}), new ConversationPrompt({message: '', user_created:false})]
|
const tempConversations: ConversationPrompt[] = [...conversationDetails, new ConversationPrompt({message: prompt, user_created:true}), new ConversationPrompt({message: '', user_created:false})]
|
||||||
|
|
||||||
@@ -135,7 +136,7 @@ const AsyncDashboardInner =({}): JSX.Element => {
|
|||||||
setConversationDetails(tempConversations)
|
setConversationDetails(tempConversations)
|
||||||
// TODO: add the file here
|
// TODO: add the file here
|
||||||
|
|
||||||
sendMessage(prompt, selectedConversation, file, fileType)
|
sendMessage(prompt, selectedConversation, file, fileType, modelName)
|
||||||
resetForm();
|
resetForm();
|
||||||
|
|
||||||
|
|
||||||
@@ -205,13 +206,15 @@ return(
|
|||||||
InputProps={{
|
InputProps={{
|
||||||
endAdornment: (
|
endAdornment: (
|
||||||
<InputAdornment position='end'>
|
<InputAdornment position='end'>
|
||||||
{/* <CustomSelect
|
<Select
|
||||||
name="category"
|
id="modelSelect"
|
||||||
items={models}
|
label="Model"
|
||||||
label="Category"
|
value={formik.values}
|
||||||
required
|
required
|
||||||
|
onChange={(e) => {console.log(e.target.value); formik.setFieldValue('modelName', e.target.value)}}
|
||||||
/> */}
|
>
|
||||||
|
{MODELS.map((model) => <MenuItem value={model} >{model}</MenuItem>)}
|
||||||
|
</Select>
|
||||||
<MDButton
|
<MDButton
|
||||||
component="label"
|
component="label"
|
||||||
startIcon={<AttachFile/>}
|
startIcon={<AttachFile/>}
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ const ConversationDetail = ({selectedConversation, conversationTitle,conversatio
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// now we want to stream the new response
|
// now we want to stream the new response
|
||||||
const eventSource = new EventSource("http://127.0.0.1:8000/api/streamed_response")
|
const eventSource = new EventSource("http://127.0.0.1:8011/api/streamed_response")
|
||||||
try{
|
try{
|
||||||
|
|
||||||
eventSource.onmessage = (event) => {
|
eventSource.onmessage = (event) => {
|
||||||
|
|||||||
@@ -0,0 +1,329 @@
|
|||||||
|
import { useEffect, useState } from "react";
|
||||||
|
import MDBox from "../../ui-kit/components/MDBox";
|
||||||
|
import { Box, Button, Card, CardContent, Divider, IconButton, Paper, Switch, Table, TableBody, TableCell, TableContainer, TableHead, TableRow } from "@mui/material";
|
||||||
|
import { Document, DocumentType } from "../../data";
|
||||||
|
import { AxiosResponse } from "axios";
|
||||||
|
import { axiosInstance } from "../../../axiosApi";
|
||||||
|
import Header2 from "../../components/Header2/Header2";
|
||||||
|
import PageWrapperLayout from "../../components/PageWrapperLayout/PageWrapperLayout";
|
||||||
|
import Footer from "../../components/Footer/Footer";
|
||||||
|
import MDTypography from "../../ui-kit/components/MDTypography";
|
||||||
|
import FeedbackSubmitCard from "../../components/FeedbackSubmitCard/FeedbackSubmitCard";
|
||||||
|
import { CheckCircle, CloudUpload, DeleteForever, Pending } from "@mui/icons-material";
|
||||||
|
import { Formik } from "formik";
|
||||||
|
import MDButton from "../../ui-kit/components/MDButton";
|
||||||
|
import PaginatedTable from "../../components/PaginatedTable/PaginatedTable";
|
||||||
|
|
||||||
|
type DocumentLineProps = {
|
||||||
|
document: Document,
|
||||||
|
handleDocumentUpdate: (document_id: number, value: string) => void
|
||||||
|
}
|
||||||
|
|
||||||
|
type DocumentTableCardProps = {
|
||||||
|
documents: Document[],
|
||||||
|
setDocuments: React.Dispatch<React.SetStateAction<Document[]>>
|
||||||
|
}
|
||||||
|
|
||||||
|
const DocumentStorageTableRow = ({document, handleDocumentUpdate}: DocumentLineProps): JSX.Element =>
|
||||||
|
{
|
||||||
|
return(
|
||||||
|
<TableRow key={document.id}>
|
||||||
|
<TableCell><MDTypography> {document.name}</MDTypography></TableCell>
|
||||||
|
<TableCell><MDTypography> {document.date_uploaded}</MDTypography></TableCell>
|
||||||
|
|
||||||
|
<TableCell>
|
||||||
|
{ document.processed ? (
|
||||||
|
<IconButton onClick={() => console.log('clicked')}>
|
||||||
|
<CheckCircle color="success" />
|
||||||
|
</IconButton>
|
||||||
|
|
||||||
|
):(
|
||||||
|
<IconButton onClick={() => console.log('clicked')}>
|
||||||
|
<Pending color="disabled" />
|
||||||
|
</IconButton>
|
||||||
|
|
||||||
|
)}
|
||||||
|
|
||||||
|
</TableCell>
|
||||||
|
<TableCell >
|
||||||
|
<Switch checked={document.active} disabled={true} onChange={(event) => handleDocumentUpdate(document.id, event.target.value)} />
|
||||||
|
</TableCell>
|
||||||
|
|
||||||
|
</TableRow>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const CompanyDocumentStorageTableCard =({documents, setDocuments}: DocumentTableCardProps): JSX.Element => {
|
||||||
|
|
||||||
|
const handleDocumentUpdate = async(document_id: number, value: string): Promise<void> => {
|
||||||
|
console.log(document_id, value)
|
||||||
|
// if(field === 'delete'){
|
||||||
|
// await axiosInstance.delete(`/company_users`, {
|
||||||
|
// data: {'email':email}
|
||||||
|
|
||||||
|
// })
|
||||||
|
// }else {
|
||||||
|
// await axiosInstance.post(`/company_users`, {
|
||||||
|
// 'email':email,
|
||||||
|
// 'field': field,
|
||||||
|
// 'value': value
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// // get all of th edata again
|
||||||
|
// try{
|
||||||
|
// const {data, }: AxiosResponse<AccountType[]> = await axiosInstance.get(`/company_users`);
|
||||||
|
// setUsers(data.map((item) => new Account({
|
||||||
|
|
||||||
|
// email: item.email,
|
||||||
|
// first_name: item.first_name,
|
||||||
|
// last_name: item.last_name,
|
||||||
|
// is_company_manager: item.is_company_manager,
|
||||||
|
// has_password: item.has_usable_password,
|
||||||
|
// is_active: item.is_active,
|
||||||
|
// company: undefined
|
||||||
|
// })))
|
||||||
|
|
||||||
|
|
||||||
|
// }catch(error){
|
||||||
|
// console.log(error)
|
||||||
|
// }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getUploadedDocuments(){
|
||||||
|
try{
|
||||||
|
const {data, }: AxiosResponse<DocumentType[]> = await axiosInstance.get(`/documents/`);
|
||||||
|
setDocuments(data.map((item) => new Document({
|
||||||
|
|
||||||
|
id: item.id,
|
||||||
|
name: item.file.replace(/^.*[\\\/]/, ''),
|
||||||
|
date_uploaded: item.created.substring(0,10),
|
||||||
|
active: item.active,
|
||||||
|
processed: item.processed,
|
||||||
|
|
||||||
|
})))
|
||||||
|
|
||||||
|
|
||||||
|
}catch(error){
|
||||||
|
console.log(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(()=>{
|
||||||
|
getUploadedDocuments();
|
||||||
|
}, [])
|
||||||
|
return (
|
||||||
|
<Card sx={{mt:1}}>
|
||||||
|
|
||||||
|
<CardContent>
|
||||||
|
<MDTypography variant="h3">
|
||||||
|
Your documents in the company workspace
|
||||||
|
|
||||||
|
</MDTypography>
|
||||||
|
</CardContent>
|
||||||
|
<CardContent>
|
||||||
|
<PaginatedTable
|
||||||
|
data={documents}
|
||||||
|
columns={[
|
||||||
|
{key: 'name', label: 'Name'},
|
||||||
|
{key: 'date_uploaded', label: 'Date Uploaded'},
|
||||||
|
{
|
||||||
|
key: 'processed',
|
||||||
|
label: 'Processed',
|
||||||
|
render: (value) =>( value ? (
|
||||||
|
<IconButton onClick={() => console.log('clicked')}>
|
||||||
|
<CheckCircle color="success" />
|
||||||
|
</IconButton>
|
||||||
|
|
||||||
|
):(
|
||||||
|
<IconButton onClick={() => console.log('clicked')}>
|
||||||
|
<Pending color="disabled" />
|
||||||
|
</IconButton>
|
||||||
|
|
||||||
|
))},
|
||||||
|
{
|
||||||
|
key: 'active',
|
||||||
|
label: 'Active',
|
||||||
|
render: (value) => (
|
||||||
|
<Switch checked={value} disabled={true} />
|
||||||
|
)
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const UserDocumentStorageTableCard = ({}): JSX.Element => {
|
||||||
|
return(
|
||||||
|
<Card sx={{mt:1}}>
|
||||||
|
|
||||||
|
<CardContent>
|
||||||
|
<MDTypography variant="h3">
|
||||||
|
Your documents in the your personal workspace
|
||||||
|
|
||||||
|
</MDTypography>
|
||||||
|
</CardContent>
|
||||||
|
<CardContent>
|
||||||
|
<MDTypography>This will become available shortly</MDTypography>
|
||||||
|
{/* <TableContainer component={Paper}>
|
||||||
|
<Table >
|
||||||
|
<TableHead sx={{ display: "table-header-group" }}>
|
||||||
|
<TableRow>
|
||||||
|
<TableCell><MDTypography>Name</MDTypography></TableCell>
|
||||||
|
<TableCell><MDTypography>Date Uploaded</MDTypography></TableCell>
|
||||||
|
<TableCell><MDTypography>Processed</MDTypography></TableCell>
|
||||||
|
<TableCell><MDTypography>Active</MDTypography></TableCell>
|
||||||
|
</TableRow>
|
||||||
|
</TableHead>
|
||||||
|
<TableBody>
|
||||||
|
|
||||||
|
<MDTypography>This will become available shortly</MDTypography>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</TableBody>
|
||||||
|
</Table>
|
||||||
|
</TableContainer> */}
|
||||||
|
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
type DocumentSubmitValues = {
|
||||||
|
document: File
|
||||||
|
}
|
||||||
|
|
||||||
|
const DocumentUploadCard = ({}): JSX.Element => {
|
||||||
|
const [selectedFile, setSelectedFile] = useState<File | null>(null);
|
||||||
|
const initialValues = {'file': '',}
|
||||||
|
|
||||||
|
const handleDocumentUpload = async ({document}: DocumentSubmitValues): Promise<void> => {
|
||||||
|
|
||||||
|
console.log(selectedFile)
|
||||||
|
if(selectedFile){
|
||||||
|
|
||||||
|
|
||||||
|
try{
|
||||||
|
const reader = new FileReader();
|
||||||
|
reader.onload = () => {
|
||||||
|
const base64File = reader.result?.toString().split(',')[1];
|
||||||
|
axiosInstance.post('/documents/', {
|
||||||
|
file: selectedFile
|
||||||
|
},
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'multipart/form-data',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
reader.readAsDataURL(selectedFile)
|
||||||
|
|
||||||
|
|
||||||
|
// TODO set the documents here
|
||||||
|
}
|
||||||
|
finally{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// const handleDocumentUpload = async ({email}: InviteValues, {resetForm}: any): Promise<void> => {
|
||||||
|
// try{
|
||||||
|
// await axiosInstance.post('/documents/', {
|
||||||
|
// 'file': file
|
||||||
|
// })
|
||||||
|
// getCompanyUsers()
|
||||||
|
|
||||||
|
// } catch{
|
||||||
|
// // put a message here
|
||||||
|
// }
|
||||||
|
// resetForm();
|
||||||
|
|
||||||
|
// }
|
||||||
|
const handleFileChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
|
if (event.target.files && event.target.files.length > 0) {
|
||||||
|
setSelectedFile(event.target.files[0]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return(
|
||||||
|
<Card sx={{mt:1}}>
|
||||||
|
<CardContent>
|
||||||
|
<MDTypography variant="h3">
|
||||||
|
Upload a Document
|
||||||
|
|
||||||
|
</MDTypography>
|
||||||
|
</CardContent>
|
||||||
|
<Divider />
|
||||||
|
|
||||||
|
<CardContent>
|
||||||
|
<Box sx={{ p: 2 }}>
|
||||||
|
|
||||||
|
|
||||||
|
<Box sx={{ display: 'flex', alignItems: 'center', mb: 2 }}>
|
||||||
|
<MDButton
|
||||||
|
component="label"
|
||||||
|
variant="contained"
|
||||||
|
startIcon={<CloudUpload />}
|
||||||
|
>
|
||||||
|
Select File
|
||||||
|
<input type="file" hidden onChange={handleFileChange} />
|
||||||
|
</MDButton>
|
||||||
|
|
||||||
|
{selectedFile && (
|
||||||
|
<>
|
||||||
|
<MDTypography sx={{ ml: 2 }}>{selectedFile.name}</MDTypography>
|
||||||
|
<MDButton
|
||||||
|
variant="contained"
|
||||||
|
color="primary"
|
||||||
|
sx={{ ml: 2 }}
|
||||||
|
onClick={handleDocumentUpload}
|
||||||
|
>
|
||||||
|
Upload
|
||||||
|
</MDButton>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const DocumentStoragePageInner = ({}): JSX.Element => {
|
||||||
|
const [documents, setDocuments] = useState<Document[]>([]);
|
||||||
|
return(
|
||||||
|
<>
|
||||||
|
<CompanyDocumentStorageTableCard documents={documents} setDocuments={setDocuments}/>
|
||||||
|
<UserDocumentStorageTableCard />
|
||||||
|
<DocumentUploadCard />
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const DocumentStoragePage = ({}): JSX.Element => {
|
||||||
|
return (
|
||||||
|
<PageWrapperLayout>
|
||||||
|
<Header2 />
|
||||||
|
<MDBox sx={{mt:12}}>
|
||||||
|
|
||||||
|
</MDBox>
|
||||||
|
<MDBox sx={{ margin: '0 auto', width: '80%', height: '80%', minHeight: '80%', maxHeight: '80%', align:'center'}}>
|
||||||
|
<DocumentStoragePageInner />
|
||||||
|
<Footer />
|
||||||
|
</MDBox>
|
||||||
|
|
||||||
|
</PageWrapperLayout>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default DocumentStoragePage;
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import MDBox from "../../ui-kit/components/MDBox";
|
import MDBox from "../../ui-kit/components/MDBox";
|
||||||
import { CardContent, Paper, Table, TableBody, TableCell, TableContainer, TableHead, TableRow } from "@mui/material";
|
import { Card, CardContent, Paper, Table, TableBody, TableCell, TableContainer, TableHead, TableRow } from "@mui/material";
|
||||||
import { Feedback, FeedbackType } from "../../data";
|
import { Feedback, FeedbackType } from "../../data";
|
||||||
import { AxiosResponse } from "axios";
|
import { AxiosResponse } from "axios";
|
||||||
import { axiosInstance } from "../../../axiosApi";
|
import { axiosInstance } from "../../../axiosApi";
|
||||||
@@ -9,21 +9,7 @@ import PageWrapperLayout from "../../components/PageWrapperLayout/PageWrapperLay
|
|||||||
import Footer from "../../components/Footer/Footer";
|
import Footer from "../../components/Footer/Footer";
|
||||||
import MDTypography from "../../ui-kit/components/MDTypography";
|
import MDTypography from "../../ui-kit/components/MDTypography";
|
||||||
import FeedbackSubmitCard from "../../components/FeedbackSubmitCard/FeedbackSubmitCard";
|
import FeedbackSubmitCard from "../../components/FeedbackSubmitCard/FeedbackSubmitCard";
|
||||||
|
import PaginatedTable from "../../components/PaginatedTable/PaginatedTable";
|
||||||
type FeedbackLineProps = {
|
|
||||||
feedback: Feedback
|
|
||||||
}
|
|
||||||
|
|
||||||
const FeedbackLine = ({feedback}: FeedbackLineProps): JSX.Element => {
|
|
||||||
return(
|
|
||||||
<TableRow key={feedback.id}>
|
|
||||||
<TableCell><MDTypography>{feedback.title}</MDTypography></TableCell>
|
|
||||||
<TableCell><MDTypography>{feedback.category}</MDTypography></TableCell>
|
|
||||||
<TableCell><MDTypography>{feedback.text}</MDTypography></TableCell>
|
|
||||||
<TableCell><MDTypography>{feedback.status}</MDTypography></TableCell>
|
|
||||||
</TableRow>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
type FeedbackTableCardProps = {
|
type FeedbackTableCardProps = {
|
||||||
feedbacks: Feedback[],
|
feedbacks: Feedback[],
|
||||||
@@ -53,27 +39,29 @@ const FeedbackTableCard =({feedbacks, setFeedbacks}: FeedbackTableCardProps): JS
|
|||||||
useEffect(()=>{
|
useEffect(()=>{
|
||||||
getCompanyUsers();
|
getCompanyUsers();
|
||||||
}, [])
|
}, [])
|
||||||
return (
|
return(
|
||||||
<CardContent>
|
<Card sx={{mt:1}}>
|
||||||
<TableContainer component={Paper}>
|
|
||||||
<Table >
|
|
||||||
<TableHead sx={{ display: "table-header-group" }}>
|
|
||||||
<TableRow>
|
|
||||||
<TableCell><MDTypography>Title</MDTypography></TableCell>
|
|
||||||
<TableCell><MDTypography>Category</MDTypography></TableCell>
|
|
||||||
<TableCell><MDTypography>Text</MDTypography></TableCell>
|
|
||||||
<TableCell><MDTypography>Status</MDTypography></TableCell>
|
|
||||||
</TableRow>
|
|
||||||
</TableHead>
|
|
||||||
<TableBody>
|
|
||||||
{feedbacks.map((feedback) => <FeedbackLine key={feedback.id} feedback={feedback}/>)}
|
|
||||||
|
|
||||||
</TableBody>
|
<CardContent>
|
||||||
</Table>
|
<MDTypography variant="h3">
|
||||||
</TableContainer>
|
Feedback
|
||||||
|
|
||||||
|
</MDTypography>
|
||||||
|
</CardContent>
|
||||||
|
<CardContent>
|
||||||
|
<PaginatedTable
|
||||||
|
data={feedbacks}
|
||||||
|
columns={[
|
||||||
|
{key: 'title', label: 'Title'},
|
||||||
|
{key: 'category', label: 'Category'},
|
||||||
|
{key: 'text', label: 'Text'},
|
||||||
|
{key: 'status', label: 'Status'},
|
||||||
|
]}
|
||||||
|
/>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
)
|
</Card>
|
||||||
|
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const FeedbackPageInner =({}): JSX.Element => {
|
const FeedbackPageInner =({}): JSX.Element => {
|
||||||
|
|||||||
@@ -1,17 +1,38 @@
|
|||||||
import { Form, Formik } from 'formik';
|
import { Form, Formik } from 'formik';
|
||||||
import React, { Dispatch, PropsWithChildren, SetStateAction, useState } from 'react';
|
import React, { useRef } from 'react';
|
||||||
import CustomPasswordField from '../../components/CustomPasswordField/CustomPasswordField';
|
|
||||||
import { Button } from '@mui/material';
|
import { Card, CardContent, Divider } from '@mui/material';
|
||||||
import { axiosInstance } from '../../../axiosApi';
|
import { axiosInstance, cleanAxiosInstance } from '../../../axiosApi';
|
||||||
import CustomToastMessage from '../../components/CustomToastMessage/CustomeToastMessage';
|
import CustomToastMessage from '../../components/CustomToastMessage/CustomeToastMessage';
|
||||||
|
import PageWrapperLayout from '../../components/PageWrapperLayout/PageWrapperLayout';
|
||||||
|
import MDBox from '../../ui-kit/components/MDBox';
|
||||||
|
import background from '../../../bg.jpeg'
|
||||||
|
import { Col, Row } from 'react-bootstrap';
|
||||||
|
import MDTypography from '../../ui-kit/components/MDTypography';
|
||||||
|
import CustomTextField from '../../components/CustomTextField/CustomTextField';
|
||||||
|
import MDButton from '../../ui-kit/components/MDButton';
|
||||||
|
import { useNavigate } from 'react-router-dom';
|
||||||
|
|
||||||
|
import ReCAPTCHA from 'react-google-recaptcha';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export type PasswordResetValues = {
|
export type PasswordResetValues = {
|
||||||
password1: string;
|
password1: string;
|
||||||
password2: string;
|
password2: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type EmailPasswordResetValues = {
|
||||||
|
email: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const PasswordReset = ({}): JSX.Element => {
|
const PasswordReset = ({}): JSX.Element => {
|
||||||
|
const navigate = useNavigate();
|
||||||
|
const recaptchaRef = useRef<ReCAPTCHA>(null);
|
||||||
|
|
||||||
const handlePasswordReset = ({password1, password2}: PasswordResetValues): void => {
|
const handlePasswordReset = ({password1, password2}: PasswordResetValues): void => {
|
||||||
try{
|
try{
|
||||||
// verify
|
// verify
|
||||||
@@ -27,73 +48,165 @@ const PasswordReset = ({}): JSX.Element => {
|
|||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const handlePasswordResetEmail = ({email}: EmailPasswordResetValues): void => {
|
||||||
|
if(recaptchaRef.current){
|
||||||
|
const token = recaptchaRef.current.getValue();
|
||||||
|
if (!token) {
|
||||||
|
|
||||||
|
try{
|
||||||
|
cleanAxiosInstance.post('user/reset_password',
|
||||||
|
{
|
||||||
|
'email': email,
|
||||||
|
'recaptchaToken': token
|
||||||
|
}
|
||||||
|
);
|
||||||
|
// navigate to another page now
|
||||||
|
navigate('/password_reset_confirmation')
|
||||||
|
}catch(error){
|
||||||
|
console.log('error')
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='main-content' style={{'height': '100%', minHeight: '100vh', display: 'flex', flexDirection: 'column'}}>
|
<PageWrapperLayout>
|
||||||
<div className='container my-auto'>
|
<MDBox sx={{'height': '100%', minHeight: '100vh', display: 'flex', flexDirection: 'column', backgroundImage: `url(${background})`,backgroundSize: "cover",
|
||||||
<div className='row'>
|
backgroundRepeat: "no-repeat",}}>
|
||||||
<div className='col -lg-4 col-md-8 col-12 mx-auto'>
|
|
||||||
<div className='card z-index-0 fadeIn3 fadeInBottom'>
|
<MDBox sx={{ margin: '0 auto', width: '80%', height: '80%', minHeight: '80%', maxHeight: '80%', align:'center'}}>
|
||||||
<div className='card-header p-0 position-relative mt-n4 mx-3 z-index-2'>
|
<Row>
|
||||||
<div className='bg-gradient-dark shadow-dark border-radius-lg py-3 pe-1'>
|
<Col className='col -lg-4 col-md-8 col-12 mx-auto'>
|
||||||
<h4 className='text-white font-weight-bold text-center'>Password Reset</h4>
|
<Card sx={{mt:30}} >
|
||||||
</div>
|
<CardContent>
|
||||||
</div>
|
<MDTypography variant="h3">
|
||||||
<div className='card-body text-center'>
|
Reset Password
|
||||||
|
</MDTypography>
|
||||||
|
</CardContent>
|
||||||
|
<Divider />
|
||||||
<Formik
|
<Formik
|
||||||
initialValues={{
|
initialValues={{
|
||||||
password1: '',
|
email: '',
|
||||||
password2: '',
|
}}
|
||||||
}}
|
onSubmit={handlePasswordResetEmail}
|
||||||
onSubmit={handlePasswordReset}>
|
|
||||||
|
>
|
||||||
{(formik) => (
|
{(formik) => (
|
||||||
<Form>
|
<Form>
|
||||||
<div className='row'>
|
<div className='row'>
|
||||||
<div className='col'>
|
<div className='col'>
|
||||||
<CustomPasswordField
|
<CustomTextField
|
||||||
label='Password'
|
label='Email'
|
||||||
name="password1"
|
name="email"
|
||||||
changeHandler={(e) => formik.setFieldValue('password1', e.target.value)} />
|
changeHandler={(e) => formik.setFieldValue('email', e.target.value)} isMultline={false}/>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className='row'>
|
<div className='row'>
|
||||||
<div className='col'>
|
<div className='col'>
|
||||||
<CustomPasswordField
|
<ReCAPTCHA
|
||||||
label='Confirm Password'
|
ref={recaptchaRef}
|
||||||
name="password2"
|
sitekey = "6LfENu4qAAAAAFtPejcrP3dwBDxcRPjqi7RhytJJ"
|
||||||
changeHandler={(e) => formik.setFieldValue('password2', e.target.value)} />
|
size="invisible"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<MDButton
|
||||||
|
type={'submit'}
|
||||||
|
fullWidth
|
||||||
|
>
|
||||||
|
<MDTypography
|
||||||
|
as="h6">
|
||||||
|
Rest Password
|
||||||
|
|
||||||
</div>
|
</MDTypography>
|
||||||
|
|
||||||
|
</MDButton>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className='row'>
|
|
||||||
<div className='col'>
|
|
||||||
<Button
|
|
||||||
type={'submit'}
|
|
||||||
disabled={ formik.isSubmitting}
|
|
||||||
// type={'submit'}
|
|
||||||
// loading={formik.isSubmitting}
|
|
||||||
// disabled={
|
|
||||||
// !formik.isValid || !formik.dirty || formik.isSubmitting
|
|
||||||
// }
|
|
||||||
>
|
|
||||||
Reset Password
|
|
||||||
</Button>
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</Form>
|
</Form>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
</Formik>
|
</Formik>
|
||||||
</div>
|
</Card>
|
||||||
</div>
|
</Col>
|
||||||
</div>
|
</Row>
|
||||||
</div>
|
</MDBox>
|
||||||
</div>
|
</MDBox>
|
||||||
</div>
|
|
||||||
|
</PageWrapperLayout>
|
||||||
|
// <div className='main-content' style={{'height': '100%', minHeight: '100vh', display: 'flex', flexDirection: 'column'}}>
|
||||||
|
// <div className='container my-auto'>
|
||||||
|
// <div className='row'>
|
||||||
|
// <div className='col -lg-4 col-md-8 col-12 mx-auto'>
|
||||||
|
// <div className='card z-index-0 fadeIn3 fadeInBottom'>
|
||||||
|
// <div className='card-header p-0 position-relative mt-n4 mx-3 z-index-2'>
|
||||||
|
// <div className='bg-gradient-dark shadow-dark border-radius-lg py-3 pe-1'>
|
||||||
|
// <h4 className='text-white font-weight-bold text-center'>Password Reset</h4>
|
||||||
|
// </div>
|
||||||
|
// </div>
|
||||||
|
// <div className='card-body text-center'>
|
||||||
|
// <Formik
|
||||||
|
// initialValues={{
|
||||||
|
// password1: '',
|
||||||
|
// password2: '',
|
||||||
|
// }}
|
||||||
|
// onSubmit={handlePasswordReset}>
|
||||||
|
// {(formik) => (
|
||||||
|
// <Form>
|
||||||
|
// <div className='row'>
|
||||||
|
// <div className='col'>
|
||||||
|
// <CustomPasswordField
|
||||||
|
// label='Password'
|
||||||
|
// name="password1"
|
||||||
|
// changeHandler={(e) => formik.setFieldValue('password1', e.target.value)} />
|
||||||
|
|
||||||
|
// </div>
|
||||||
|
// </div>
|
||||||
|
// <div className='row'>
|
||||||
|
// <div className='col'>
|
||||||
|
// <CustomPasswordField
|
||||||
|
// label='Confirm Password'
|
||||||
|
// name="password2"
|
||||||
|
// changeHandler={(e) => formik.setFieldValue('password2', e.target.value)} />
|
||||||
|
|
||||||
|
// </div>
|
||||||
|
// </div>
|
||||||
|
// <div className='row'>
|
||||||
|
// <div className='col'>
|
||||||
|
// <Button
|
||||||
|
// type={'submit'}
|
||||||
|
// disabled={ formik.isSubmitting}
|
||||||
|
// // type={'submit'}
|
||||||
|
// // loading={formik.isSubmitting}
|
||||||
|
// // disabled={
|
||||||
|
// // !formik.isValid || !formik.dirty || formik.isSubmitting
|
||||||
|
// // }
|
||||||
|
// >
|
||||||
|
// Reset Password
|
||||||
|
// </Button>
|
||||||
|
|
||||||
|
|
||||||
|
// </div>
|
||||||
|
// </div>
|
||||||
|
|
||||||
|
// </Form>
|
||||||
|
// )}
|
||||||
|
|
||||||
|
// </Formik>
|
||||||
|
// </div>
|
||||||
|
// </div>
|
||||||
|
// </div>
|
||||||
|
// </div>
|
||||||
|
// </div>
|
||||||
|
// </div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,59 @@
|
|||||||
|
import { Form, Formik } from 'formik';
|
||||||
|
import React, { Dispatch, PropsWithChildren, SetStateAction, useState } from 'react';
|
||||||
|
import CustomPasswordField from '../../components/CustomPasswordField/CustomPasswordField';
|
||||||
|
import { Button, Card, CardContent, Divider } from '@mui/material';
|
||||||
|
import { axiosInstance } from '../../../axiosApi';
|
||||||
|
import CustomToastMessage from '../../components/CustomToastMessage/CustomeToastMessage';
|
||||||
|
import PageWrapperLayout from '../../components/PageWrapperLayout/PageWrapperLayout';
|
||||||
|
import MDBox from '../../ui-kit/components/MDBox';
|
||||||
|
import background from '../../../bg.jpeg'
|
||||||
|
import { Col, Row } from 'react-bootstrap';
|
||||||
|
import MDTypography from '../../ui-kit/components/MDTypography';
|
||||||
|
import { valuesIn } from 'lodash';
|
||||||
|
import CustomTextField from '../../components/CustomTextField/CustomTextField';
|
||||||
|
import MDButton from '../../ui-kit/components/MDButton';
|
||||||
|
import { useNavigate } from 'react-router-dom';
|
||||||
|
|
||||||
|
export type PasswordResetValues = {
|
||||||
|
password1: string;
|
||||||
|
password2: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type EmailPasswordResetValues = {
|
||||||
|
email: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const PasswordResetConfirmation = ({}): JSX.Element => {
|
||||||
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
<PageWrapperLayout>
|
||||||
|
<MDBox sx={{'height': '100%', minHeight: '100vh', display: 'flex', flexDirection: 'column', backgroundImage: `url(${background})`,backgroundSize: "cover",
|
||||||
|
backgroundRepeat: "no-repeat",}}>
|
||||||
|
|
||||||
|
<MDBox sx={{ margin: '0 auto', width: '80%', height: '80%', minHeight: '80%', maxHeight: '80%', align:'center'}}>
|
||||||
|
<Row>
|
||||||
|
<Col className='col -lg-4 col-md-8 col-12 mx-auto'>
|
||||||
|
<Card sx={{mt:30}} >
|
||||||
|
<CardContent>
|
||||||
|
<MDTypography variant="h3">
|
||||||
|
Reset Password Confirmation
|
||||||
|
</MDTypography>
|
||||||
|
</CardContent>
|
||||||
|
<Divider />
|
||||||
|
<MDTypography>
|
||||||
|
Check your email for a link to set your password!
|
||||||
|
</MDTypography>
|
||||||
|
|
||||||
|
</Card>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
</MDBox>
|
||||||
|
</MDBox>
|
||||||
|
|
||||||
|
</PageWrapperLayout>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default PasswordResetConfirmation;
|
||||||
@@ -90,6 +90,8 @@ const SignIn = ({}): JSX.Element => {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PageWrapperLayout>
|
<PageWrapperLayout>
|
||||||
@@ -140,15 +142,34 @@ const SignIn = ({}): JSX.Element => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className='row'>
|
<div className='row'>
|
||||||
<div className='col'>
|
<div className='col-6'>
|
||||||
<MDButton
|
<MDButton
|
||||||
type={'submit'}
|
type={'submit'}
|
||||||
|
fullWidth
|
||||||
>
|
>
|
||||||
Sign In
|
<MDTypography
|
||||||
</MDButton>
|
as="h6">
|
||||||
|
Sign In
|
||||||
|
|
||||||
|
</MDTypography>
|
||||||
|
|
||||||
|
</MDButton>
|
||||||
</div>
|
</div>
|
||||||
|
{/* <div className='col-6'>
|
||||||
|
<MDButton
|
||||||
|
fullWidth
|
||||||
|
onClick={() => navigate('/password_reset')}
|
||||||
|
>
|
||||||
|
<MDTypography
|
||||||
|
color="error"
|
||||||
|
as="h6"
|
||||||
|
>
|
||||||
|
Reset Password
|
||||||
|
|
||||||
|
</MDTypography>
|
||||||
|
|
||||||
|
</MDButton>
|
||||||
|
</div> */}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</Form>
|
</Form>
|
||||||
|
|||||||
Reference in New Issue
Block a user