a b/frontend/src/home.js
1
import React, { useState, useEffect, useCallback } from "react";
2
import { makeStyles, withStyles } from "@material-ui/core/styles";
3
import AppBar from "@material-ui/core/AppBar";
4
import Toolbar from "@material-ui/core/Toolbar";
5
import Typography from "@material-ui/core/Typography";
6
import Avatar from "@material-ui/core/Avatar";
7
import Container from "@material-ui/core/Container";
8
import cblogo from "./cblogo.PNG";
9
import Image from "./bg.png";
10
import Card from "@material-ui/core/Card";
11
import CardContent from "@material-ui/core/CardContent";
12
import { Paper, CardActionArea, CardMedia, Grid, TableContainer, Table, TableBody, TableHead, TableRow, TableCell, Button, CircularProgress } from "@material-ui/core";
13
import Clear from '@material-ui/icons/Clear';
14
import { DropzoneArea } from 'material-ui-dropzone';
15
16
const ColorButton = withStyles((theme) => ({
17
  root: {
18
    color: theme.palette.getContrastText(theme.palette.common.white),
19
    backgroundColor: theme.palette.common.white,
20
    '&:hover': {
21
      backgroundColor: '#ffffff7a',
22
    },
23
  },
24
}))(Button);
25
26
const axios = require("axios").default;
27
28
const useStyles = makeStyles((theme) => ({
29
  grow: {
30
    flexGrow: 1,
31
  },
32
  clearButton: {
33
    width: "-webkit-fill-available",
34
    borderRadius: "15px",
35
    padding: "15px 22px",
36
    color: "#000000a6",
37
    fontSize: "20px",
38
    fontWeight: 900,
39
  },
40
  root: {
41
    maxWidth: 345,
42
    flexGrow: 1,
43
  },
44
  media: {
45
    height: 400,
46
  },
47
  paper: {
48
    padding: theme.spacing(2),
49
    margin: 'auto',
50
    maxWidth: 500,
51
  },
52
  gridContainer: {
53
    justifycontent: "center",
54
    padding: "4em 1em 0 1em",
55
  },
56
  mainContainer: {
57
    backgroundImage: `url(${Image})`,
58
    backgroundRepeat: 'no-repeat',
59
    backgroundPosition: 'center',
60
    backgroundSize: 'cover',
61
    height: "93vh",
62
    marginTop: "8px",
63
  },
64
  ImageCard: {
65
    margin: "auto",
66
    maxWidth: 400,
67
    height: 500,
68
    backgroundColor: 'transparent',
69
    boxShadow: '0px 9px 70px 0px rgb(0 0 0 / 30%) !important',
70
    borderRadius: '15px',
71
  },
72
  ImageCardEmpty: {
73
    height: 'auto',
74
  },
75
  noImage: {
76
    margin: "auto",
77
    width: 400,
78
    height: "400 !important",
79
  },
80
  input: {
81
    display: 'none',
82
  },
83
  uploadIcon: {
84
    background: 'white',
85
  },
86
  tableContainer: {
87
    backgroundColor: 'transparent !important',
88
    boxShadow: 'none !important',
89
  },
90
  table: {
91
    backgroundColor: 'transparent !important',
92
  },
93
  tableHead: {
94
    backgroundColor: 'transparent !important',
95
  },
96
  tableRow: {
97
    backgroundColor: 'transparent !important',
98
  },
99
  tableCell: {
100
    fontSize: '22px',
101
    backgroundColor: 'transparent !important',
102
    borderColor: 'transparent !important',
103
    color: '#000000a6 !important',
104
    fontWeight: 'bolder',
105
    padding: '1px 24px 1px 16px',
106
  },
107
  tableCell1: {
108
    fontSize: '14px',
109
    backgroundColor: 'transparent !important',
110
    borderColor: 'transparent !important',
111
    color: '#000000a6 !important',
112
    fontWeight: 'bolder',
113
    padding: '1px 24px 1px 16px',
114
  },
115
  tableBody: {
116
    backgroundColor: 'transparent !important',
117
  },
118
  text: {
119
    color: 'white !important',
120
    textAlign: 'center',
121
  },
122
  buttonGrid: {
123
    maxWidth: "416px",
124
    width: "100%",
125
  },
126
  detail: {
127
    backgroundColor: 'white',
128
    display: 'flex',
129
    justifycontent: 'center',
130
    flexDirection: 'column',
131
    alignItems: 'center',
132
  },
133
  appbar: {
134
    background: 'purple',
135
    boxShadow: 'none',
136
    color: 'white'
137
  },
138
  loader: {
139
    color: '#be6a77 !important',
140
  }
141
}));
142
143
export const ImageUpload = () => {
144
  const classes = useStyles();
145
  const [selectedFile, setSelectedFile] = useState();
146
  const [preview, setPreview] = useState();
147
  const [data, setData] = useState();
148
  const [Image, setImage] = useState(false);
149
  const [isLoading, setIsloading] = useState(false);
150
151
  let confidence = 0;
152
153
  const sendFile = useCallback(async () => {
154
    if (Image) {
155
      try {
156
        let formData = new FormData();
157
        formData.append("file", selectedFile);
158
        console.log("Before API request");
159
        let res = await axios({
160
          method: "post",
161
          url: process.env.REACT_APP_API_URL,
162
          data: formData,
163
        });
164
        console.log("After API request");
165
  
166
        if (res.status === 200) {
167
          setData(res.data);
168
        } else {
169
          // Handle other status codes here
170
          console.error(`API request failed with status code: ${res.status}`);
171
        }
172
      } catch (error) {
173
        // Handle request error (e.g., network error, server not running)
174
        console.error("API request failed:", error);
175
      } finally {
176
        setIsloading(false);
177
      }
178
    }
179
  }, [Image, selectedFile, setData, setIsloading]);
180
181
  const clearData = () => {
182
    setData(null);
183
    setImage(false);
184
    setSelectedFile(null);
185
    setPreview(null);
186
  };
187
188
  useEffect(() => {
189
    if (!selectedFile) {
190
      setPreview(undefined);
191
      return;
192
    }
193
    const objectUrl = URL.createObjectURL(selectedFile);
194
    setPreview(objectUrl);
195
  }, [selectedFile]);
196
197
  useEffect(() => {
198
    if (!preview) {
199
      return;
200
    }
201
    setIsloading(true);
202
    sendFile();
203
  }, [preview, sendFile]);
204
205
  const onSelectFile = (files) => {
206
    if (!files || files.length === 0) {
207
      setSelectedFile(undefined);
208
      setImage(false);
209
      setData(undefined);
210
      return;
211
    }
212
    setSelectedFile(files[0]);
213
    setData(undefined);
214
    setImage(true);
215
  };
216
217
  if (data) {
218
    confidence = (parseFloat(data.confidence) * 100).toFixed(2);
219
  }
220
221
  return (
222
    <React.Fragment>
223
      <AppBar position="static" className={classes.appbar}>
224
        <Toolbar>
225
          <Typography className={classes.title} variant="h6" noWrap>
226
            CSE499: Lukemia Blood cell Cancer Classification
227
          </Typography>
228
          <div className={classes.grow} />
229
          <Avatar src={cblogo}></Avatar>
230
        </Toolbar>
231
      </AppBar>
232
      <Container maxWidth={false} className={classes.mainContainer} disableGutters={true}>
233
        <Grid
234
          className={classes.gridContainer}
235
          container
236
          direction="row"
237
          justifycontent="center"
238
          alignItems="center"
239
          spacing={2}
240
        >
241
          <Grid item xs={12}>
242
            <Card className={`${classes.ImageCard} ${!Image ? classes.ImageCardEmpty : ''}`}>
243
              {Image && <CardActionArea>
244
                <CardMedia
245
                  className={classes.media}
246
                  component="img" // Change to "img"
247
                  src={preview} // Change to "src"
248
                  title="Contemplative Reptile"
249
                />
250
              </CardActionArea>
251
              }
252
              {!Image && <CardContent className={classes.content}>
253
                <DropzoneArea
254
                  acceptedFiles={['image/*']}
255
                  dropzoneText={"Drag-drop or Upload an image of Blood Cell to proceed"}
256
                  onChange={onSelectFile}
257
                />
258
              </CardContent>}
259
              {data && <CardContent className={classes.detail}>
260
                <TableContainer component={Paper} className={classes.tableContainer}>
261
                  <Table className={classes.table} size="small" aria-label="simple table">
262
                    <TableHead className={classes.tableHead}>
263
                      <TableRow className={classes.tableRow}>
264
                        <TableCell className={classes.tableCell1}>Label:</TableCell>
265
                        <TableCell align="right" className={classes.tableCell1}>Confidence:</TableCell>
266
                      </TableRow>
267
                    </TableHead>
268
                    <TableBody className={classes.tableBody}>
269
                      <TableRow className={classes.tableRow}>
270
                        <TableCell component="th" scope="row" className={classes.tableCell}>
271
                          {data.class}
272
                        </TableCell>
273
                        <TableCell align="right" className={classes.tableCell}>{confidence}%</TableCell>
274
                      </TableRow>
275
                    </TableBody>
276
                  </Table>
277
                </TableContainer>
278
              </CardContent>}
279
              {isLoading && <CardContent className={classes.detail}>
280
                <CircularProgress color="secondary" className={classes.loader} />
281
                <Typography className={classes.title} variant="h6" noWrap>
282
                  Matching... Please Wait...
283
                </Typography>
284
              </CardContent>}
285
            </Card>
286
          </Grid>
287
          {data &&
288
            <Grid item className={classes.buttonGrid} >
289
290
              <ColorButton variant="contained" className={classes.clearButton} color="primary" component="span" size="large" onClick={clearData} startIcon={<Clear fontSize="large" />}>
291
                Clear
292
              </ColorButton>
293
            </Grid>}
294
        </Grid >
295
      </Container >
296
    </React.Fragment >
297
  );
298
};