Commit e74db4ff authored by janithgamage1.ed's avatar janithgamage1.ed

Merge branch 'master' into IT20254384

parents 5452c338 529c1ff1
{
"cSpell.words": [
"formik",
"Janith",
"leaderboard",
"SLIIT"
......
......@@ -2,22 +2,25 @@ import Curriculum from '../models/curriculum.model.js';
export const getAllCurriculums = async (req, res) => {
try {
const curriculums = await Curriculum.find();
const curriculums = await Curriculum.find().populate("tutorials");
res.status(200).json(curriculums);
} catch (error) {
res.status(500).json({ message: error.message });
}
}
};
export const getCurriculumById = async (req, res) => {
const { id } = req.params;
try {
const curriculum = await Curriculum.findById(id);
const curriculum = await Curriculum.findById(id).populate("tutorials");
if (!curriculum) {
return res.status(404).json({ message: 'Curriculum not found' });
}
res.status(200).json(curriculum);
} catch (error) {
res.status(404).json({ message: 'Curriculum not found' });
res.status(500).json({ message: error.message });
}
}
};
export const createCurriculum = async (req, res) => {
const curriculumData = req.body;
......
import { exec } from "child_process";
export const marksCalculator = async (req, res) => {
const imageData = req.file.buffer.toString('base64');
const targetClass = req.body.class;
const { curriculumIndex, tutorialIndex } = req.params;
const status = "";
// console.log(curriculumIndex, tutorialIndex);
try {
if (curriculumIndex == 1 && tutorialIndex == 1) {
// Run Python script to perform prediction
const pythonProcess = exec('python prediction_config/C1T1/predict.py', (error, stdout, stderr) => {
if (error) {
console.error(error);
return res.status(500).json({ error: 'An error occurred' });
}
const [predicted_class_name, confidence] = stdout.trim().split(',');
const parsedConfidence = parseFloat(confidence).toFixed(2);
let status = "";
if (predicted_class_name === targetClass && parsedConfidence > 85) {
status = "pass";
} else {
status = "fail";
}
res.status(200).json({
code: "01",
result: {
predicted_class_name,
confidence: parsedConfidence,
status
}
});
});
pythonProcess.stdin.write(`${imageData}\n${targetClass}`);
pythonProcess.stdin.end();
} else {
return res.status(400).json({ code: "02", message: "Curriculum Index or Tutorial Index Invalid" })
}
} catch (error) {
res.status(500).json({ code: "00", message: "Something went wrong" })
}
}
\ No newline at end of file
......@@ -84,24 +84,18 @@ const curriculums = [
},
{
"tutorialCode": "02",
"tutorialTitle": "Learn the Basics of Sign Language",
"tutorialTitle": "Everyday Vocabulary in Sign Language",
"tutorialImage": "https://drive.google.com/uc?export=view&id=1YACBlu7X-O7-DKv5DoW3AM9kgfT7Yhdc",
"tutorialContent": "Introduce the concept of sign language and its importance.\nTeach basic greetings and expressions, such as hello, goodbye, thank you, and sorry.\nProvide visual demonstrations and practice exercises for learners to practice these basic signs."
},
"tutorialContent": "Teach signs for everyday objects and activities, such as eat, drink, sleep, book, pen, etc.\nIntroduce signs for common words used in daily life.\nProvide visual demonstrations and interactive exercises for learners to practice using these signs."
},
{
"tutorialCode": "03",
"tutorialTitle": "Family Signs in Sign Language",
"tutorialImage": "https://drive.google.com/uc?export=view&id=1YACBlu7X-O7-DKv5DoW3AM9kgfT7Yhdc",
"tutorialContent": "Teach signs for family members, such as mother, father, sister, brother, etc.\nIntroduce signs for common family-related words, such as family, love, and home.\nProvide visual demonstrations and practice exercises for learners to practice these family signs."
},
},
{
"tutorialCode": "04",
"tutorialTitle": "Everyday Vocabulary in Sign Language",
"tutorialImage": "https://drive.google.com/uc?export=view&id=1YACBlu7X-O7-DKv5DoW3AM9kgfT7Yhdc",
"tutorialContent": "Teach signs for everyday objects and activities, such as eat, drink, sleep, book, pen, etc.\nIntroduce signs for common words used in daily life.\nProvide visual demonstrations and interactive exercises for learners to practice using these signs."
},
{
"tutorialCode": "05",
"tutorialTitle": "Basic Conversational Phrases in Sign Language",
"tutorialImage": "https://drive.google.com/uc?export=view&id=1YACBlu7X-O7-DKv5DoW3AM9kgfT7Yhdc",
"tutorialContent": "Teach simple conversational phrases, such as \"What is your name?\" or \"How are you?\"\nIntroduce signs for common question words and phrases.\nProvide visual demonstrations and practice exercises for learners to practice these conversational phrases."
......
import mongoose from "mongoose";
const tutorialSchema = new mongoose.Schema({
tutorialCode: String,
tutorialTitle: String,
tutorialImage: String,
// Additional fields for tutorial content
});
const curriculumSchema = new mongoose.Schema({
curriculumCode: String,
curriculumLevel: String,
curriculumName: String,
curriculumImage: String,
tutorials: [tutorialSchema], // Embed tutorials as subdocuments
// Additional fields for curriculum details
status: {
type: Number,
default: 1, // Default status as active (1)
},
const commonFields = {
createdBy: String,
updatedBy: String,
createdAt: {
......@@ -28,6 +11,27 @@ const curriculumSchema = new mongoose.Schema({
type: Date,
default: new Date(),
},
};
const curriculumSchema = new mongoose.Schema({
curriculumCode: {
type: String,
unique: true, // Ensures unique values for curriculumCode
},
curriculumLevel: String,
curriculumTitle: String,
curriculumDescription: String,
curriculumImage: String,
tutorials: [{
type: mongoose.Schema.Types.ObjectId,
ref: "Tutorial",
}],
// Additional fields for curriculum details
status: {
type: Number,
default: 1, // Default status as active (1)
},
...commonFields
});
const Curriculum = mongoose.model("Curriculum", curriculumSchema);
......
import mongoose from "mongoose";
const commonFields = {
createdBy: String,
updatedBy: String,
createdAt: {
type: Date,
default: new Date(),
},
updatedAt: {
type: Date,
default: new Date(),
},
};
const taskItemSchema = new mongoose.Schema({
title: String,
description: String,
......@@ -10,8 +23,12 @@ const taskItemSchema = new mongoose.Schema({
});
const tutorialSchema = new mongoose.Schema({
tutorialCode: String,
tutorialCode: {
type: String,
unique: true, // Ensures unique values for tutorialCode
},
tutorialTitle: String,
tutorialDescription: String,
tutorialImage: String,
taskItems: [taskItemSchema], // Embed task items as subdocuments
// Additional fields for tutorial details
......@@ -19,16 +36,7 @@ const tutorialSchema = new mongoose.Schema({
type: Number,
default: 1, // Default status as active (1)
},
createdBy: String,
updatedBy: String,
createdAt: {
type: Date,
default: new Date(),
},
updatedAt: {
type: Date,
default: new Date(),
},
...commonFields
});
const Tutorial = mongoose.model("Tutorial", tutorialSchema);
......
......@@ -19,6 +19,7 @@
"multer": "^1.4.5-lts.1",
"nodemailer": "^6.9.1",
"nodemon": "^2.0.22",
"torch": "^0.2.7",
"uuid": "^9.0.0"
}
},
......@@ -58,6 +59,22 @@
"node": ">= 0.6"
}
},
"node_modules/ansi-regex": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
"integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/ansi-styles": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
"integrity": "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/anymatch": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
......@@ -190,6 +207,29 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/chalk": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
"integrity": "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==",
"dependencies": {
"ansi-styles": "^2.2.1",
"escape-string-regexp": "^1.0.2",
"has-ansi": "^2.0.0",
"strip-ansi": "^3.0.0",
"supports-color": "^2.0.0"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/chalk/node_modules/supports-color": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
"integrity": "sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==",
"engines": {
"node": ">=0.8.0"
}
},
"node_modules/chokidar": {
"version": "3.5.3",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
......@@ -343,6 +383,14 @@
"resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
"integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow=="
},
"node_modules/escape-string-regexp": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
"integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
"engines": {
"node": ">=0.8.0"
}
},
"node_modules/etag": {
"version": "1.8.1",
"resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
......@@ -526,6 +574,17 @@
"node": ">= 0.4.0"
}
},
"node_modules/has-ansi": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
"integrity": "sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg==",
"dependencies": {
"ansi-regex": "^2.0.0"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/has-flag": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
......@@ -1343,6 +1402,17 @@
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
},
"node_modules/strip-ansi": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
"integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==",
"dependencies": {
"ansi-regex": "^2.0.0"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/supports-color": {
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
......@@ -1373,6 +1443,18 @@
"node": ">=0.6"
}
},
"node_modules/torch": {
"version": "0.2.7",
"resolved": "https://registry.npmjs.org/torch/-/torch-0.2.7.tgz",
"integrity": "sha512-yTv7qWKGg00hMDv0pyBgRjubbf4eygzzrjKPKRC9rbPCKBF0jd+cxnzIoN+pCHgGf2EQbd0jGyy1X7h5BIqjEA==",
"deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.",
"dependencies": {
"chalk": "^1.1.3"
},
"engines": {
"node": ">= 0.8.4"
}
},
"node_modules/touch": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz",
......@@ -1522,6 +1604,16 @@
"negotiator": "0.6.3"
}
},
"ansi-regex": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
"integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA=="
},
"ansi-styles": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
"integrity": "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA=="
},
"anymatch": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
......@@ -1629,6 +1721,25 @@
"get-intrinsic": "^1.0.2"
}
},
"chalk": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
"integrity": "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==",
"requires": {
"ansi-styles": "^2.2.1",
"escape-string-regexp": "^1.0.2",
"has-ansi": "^2.0.0",
"strip-ansi": "^3.0.0",
"supports-color": "^2.0.0"
},
"dependencies": {
"supports-color": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
"integrity": "sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g=="
}
}
},
"chokidar": {
"version": "3.5.3",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
......@@ -1743,6 +1854,11 @@
"resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
"integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow=="
},
"escape-string-regexp": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
"integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg=="
},
"etag": {
"version": "1.8.1",
"resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
......@@ -1887,6 +2003,14 @@
"function-bind": "^1.1.1"
}
},
"has-ansi": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
"integrity": "sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg==",
"requires": {
"ansi-regex": "^2.0.0"
}
},
"has-flag": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
......@@ -2489,6 +2613,14 @@
}
}
},
"strip-ansi": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
"integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==",
"requires": {
"ansi-regex": "^2.0.0"
}
},
"supports-color": {
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
......@@ -2510,6 +2642,14 @@
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
"integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA=="
},
"torch": {
"version": "0.2.7",
"resolved": "https://registry.npmjs.org/torch/-/torch-0.2.7.tgz",
"integrity": "sha512-yTv7qWKGg00hMDv0pyBgRjubbf4eygzzrjKPKRC9rbPCKBF0jd+cxnzIoN+pCHgGf2EQbd0jGyy1X7h5BIqjEA==",
"requires": {
"chalk": "^1.1.3"
}
},
"touch": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz",
......
......@@ -21,6 +21,7 @@
"multer": "^1.4.5-lts.1",
"nodemailer": "^6.9.1",
"nodemon": "^2.0.22",
"torch": "^0.2.7",
"uuid": "^9.0.0"
}
}
import sys
import io
import base64
import torch
import torchvision.transforms as transforms
from PIL import Image
import torch.nn as nn
import torch.nn.functional as F
import numpy as np
class theCNN(nn.Module):
def __init__(self):
super().__init__()
self.conv01 = nn.Conv2d(
in_channels=1,
out_channels=10,
kernel_size=5,
stride=1,
padding=1
)
self.dropout1 = nn.Dropout(0.2) # Add dropout layer
self.conv02 = nn.Conv2d(
in_channels=10,
out_channels=20,
kernel_size=5,
stride=1,
padding=1
)
self.dropout2 = nn.Dropout(0.2) # Add dropout layer
expectedSize = np.floor((73+2*0-1)/1) + 1
expectedSize = 20*int(expectedSize**2)
self.fc01 = nn.Linear(expectedSize, 50)
self.output = nn.Linear(50, 16)
def forward(self, x):
# convo -> maxpool -> relu
x = F.relu(F.max_pool2d(self.conv01(x), 2))
# convo -> maxpool -> relu
x = F.relu(F.max_pool2d(self.conv02(x), 2))
nUnits = x.shape.numel()/x.shape[0]
x = x.view(-1, int(nUnits))
x = F.relu(self.fc01(x))
return torch.softmax(self.output(x), axis=1)
# Load the mapping dictionary
class_mapping = {
0: 'Eight',
1: 'Eleven',
2: 'Fifty',
3: 'Five',
4: 'Four',
5: 'Fourteen',
6: 'Nine',
7: 'One',
8: 'Seven',
9: 'Six',
10: 'Ten',
11: 'Thirteen',
12: 'Thirty',
13: 'Three',
14: 'Twenty',
15: 'Two'
}
# Load the trained model
model = theCNN() # Instantiate your model class
model.load_state_dict(torch.load(
'D:/SLIIT_Y4_Research_Module/Research/Project/2023-029/Project/Backend/Server_Node/prediction_config/C1T1/trained_model_modified.pth', map_location=torch.device('cpu')))
model.eval()
# Read image data and target class from standard input
input_data = sys.stdin.readlines()
image_data = input_data[0].strip().encode() # Convert to bytes
target_class = input_data[1].strip()
# Preprocess the image
# image_data = base64.b64decode(sys.argv[1])
# image = Image.open(io.BytesIO(image_data))
image = Image.open(io.BytesIO(base64.b64decode(image_data)))
transform = transforms.Compose([
transforms.Resize((300, 300)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor(),
transforms.Normalize(mean=[0.5], std=[0.5]),
])
image_tensor = transform(image).unsqueeze(0)
# Predict the class
with torch.no_grad():
outputs = model(image_tensor)
predicted_class = torch.argmax(outputs[0]).item()
confidence = outputs[0][predicted_class].item()
# Get the predicted class name using the mapping dictionary
predicted_class_name = class_mapping[predicted_class]
# Calculate similarity or confidence percentage
# target_class = sys.argv[2].lower() # Class name passed from the API
similarity = 100 * confidence
print(f"{predicted_class_name},{similarity:.2f}")
import express from "express";
import multer from "multer";
import { marksCalculator } from "../controllers/marksCalculator.controller.js";
// Set up storage for uploaded images
const storage = multer.memoryStorage();
const upload = multer({ storage: storage });
const router = express.Router();
router.post('/curriculum/:curriculumIndex/tutorial/:tutorialIndex', upload.single('image'), marksCalculator)
export default router;
\ No newline at end of file
......@@ -4,10 +4,17 @@ import dotenv from "dotenv";
import express from "express";
import mongoose from "mongoose";
import multer from "multer";
// Set up storage for uploaded images
const storage = multer.memoryStorage();
const upload = multer({ storage: storage });
//import routes
import curriculumRoutes from "./routes/curriculum.routes.js";
import feedbackRoutes from "./routes/feedback.routes.js";
import leaderboardRoutes from "./routes/leaderboard.routes.js";
import marksCalculatorRoutes from "./routes/marksCalculator.routes.js";
import translateRoutes from "./routes/translate.routes.js";
import tutorialRoutes from "./routes/tutorial.routes.js";
import userRoutes from "./routes/user.routes.js";
......@@ -33,6 +40,7 @@ app.use("/rest_node/tutorial", tutorialRoutes);
app.use("/rest_node/user-progress", userProgressRoutes);
app.use("/rest_node/feedback", feedbackRoutes);
app.use("/rest_node/leaderboard", leaderboardRoutes);
app.use("/rest_node/marks-calculator", marksCalculatorRoutes);
const CONNECTION_URL = `mongodb+srv://${process.env.DB_USERNAME}:${process.env.DB_PASSWORD}@researchmanagement-appl.vzhn4.mongodb.net/?retryWrites=true&w=majority`;
const PORT = process.env.PORT || 5000;
......
This diff is collapsed.
export interface CurriculumLevelsType {
id: number
code: string
description: string
}
// ==============================|| DATA - CURRICULUM LEVELS ||============================== //
const curriculumLevels: readonly CurriculumLevelsType[] = [
{ id: 1, code: "Level 1", description: "Preliminary" },
{ id: 2, code: "Level 2", description: "Intermediate" },
{ id: 3, code: "Level 3", description: "Advance" },
];
export default curriculumLevels;
// import { useMemo } from 'react';
import { useMemo } from 'react';
// material-ui
import { Theme } from '@mui/material/styles';
import { Box, useMediaQuery } from '@mui/material';
import { Theme } from '@mui/material/styles';
// project import
import Search from './Search';
import Localization from './Localization';
import Message from './Message';
import Profile from './Profile';
// import Localization from './Localization';
import Notification from './Notification';
import Profile from './Profile';
import Search from './Search';
// import Customization from './Customization';
import MobileSection from './MobileSection';
// import MegaMenuSection from './MegaMenuSection';
......@@ -23,13 +23,12 @@ import { MenuOrientation } from 'types/config';
// ==============================|| HEADER - CONTENT ||============================== //
const HeaderContent = () => {
// const { i18n, menuOrientation } = useConfig();
const { menuOrientation } = useConfig();
const { i18n, menuOrientation } = useConfig();
const downLG = useMediaQuery((theme: Theme) => theme.breakpoints.down('lg'));
// eslint-disable-next-line react-hooks/exhaustive-deps
// const localization = useMemo(() => <Localization />, [i18n]);
const localization = useMemo(() => <Localization />, [i18n]);
// const megaMenu = useMemo(() => <MegaMenuSection />, []);
......@@ -38,7 +37,7 @@ const HeaderContent = () => {
{menuOrientation === MenuOrientation.HORIZONTAL && !downLG && <DrawerHeader open={true} />}
{!downLG && <Search />}
{/* {!downLG && megaMenu} */}
{/* {!downLG && localization} */}
{!downLG && localization}
{downLG && <Box sx={{ width: '100%', ml: 1 }} />}
<Notification />
......
import { useEffect, useState } from 'react';
// material-ui
// third-party
import {
Box,
FormControl,
Grid,
MenuItem,
Pagination,
Select,
SelectChangeEvent,
Slide,
Stack,
Theme,
Typography,
useMediaQuery
} from '@mui/material';
// project import
import MainCard from 'components/MainCard';
import ScrollX from 'components/ScrollX';
import usePagination from 'hooks/usePagination';
import CurriculumCard from 'sections/learning-management/learning-curriculums/CurriculumCard';
import EmptyCurriculumCard from 'sections/learning-management/learning-curriculums/skeleton/EmptyCurriculumCard';
import { GlobalFilter } from 'utils/react-table';
import { dataProps } from './types/types';
// assets
// types
//types
// assets
// ==============================|| List ||============================== //
const allColumns = [
{
id: 1,
header: 'Default'
},
{
id: 2,
header: 'Code'
},
{
id: 3,
header: 'Name'
},
{
id: 4,
header: 'Level'
},
{
id: 5,
header: 'Status'
}
];
const List = () => {
const data: dataProps[] = [
{
"_id": "1",
"curriculumCode": "01",
"curriculumLevel": 1,
"curriculumDescription": "This curriculum teaches basic sign language skills to help beginners communicate effectively using sign language.",
"curriculumName": "Learn Basic Sign Language Skills",
"curriculumImage": "https://drive.google.com/uc?export=view&id=1YACBlu7X-O7-DKv5DoW3AM9kgfT7Yhdc",
"tutorials": [],
"status": 1,
"createdAt": new Date("2023-08-30T12:00:00Z"),
},
{
"_id": "2",
"curriculumCode": "02",
"curriculumLevel": 2,
"curriculumName": "Learn Intermediate Sign Language Skills",
"curriculumDescription": "This curriculum focuses on building intermediate sign language skills, allowing learners to engage in more complex conversations and interactions using sign language.",
"curriculumImage": "https://drive.google.com/uc?export=view&id=1YACBlu7X-O7-DKv5DoW3AM9kgfT7Yhdc",
"tutorials": [],
"status": 1,
"createdAt": new Date("2023-08-30T12:00:00Z"),
},
{
"_id": "3",
"curriculumCode": "03",
"curriculumLevel": 3,
"curriculumName": "Learn Advance Sign Language Skills",
"curriculumDescription": "This curriculum is designed for those who already have a solid foundation in sign language. It covers advanced topics, nuances, and cultural aspects of sign language communication.",
"curriculumImage": "https://drive.google.com/uc?export=view&id=1YACBlu7X-O7-DKv5DoW3AM9kgfT7Yhdc",
"tutorials": [],
"status": 1,
"createdAt": new Date("2023-08-30T12:00:00Z"),
}
]
const matchDownSM = useMediaQuery((theme: Theme) => theme.breakpoints.down('sm'));
const [sortBy, setSortBy] = useState('Default');
const [globalFilter, setGlobalFilter] = useState('');
const [curriculumCard, setCurriculumCard] = useState<dataProps[]>([]);
const [page, setPage] = useState(1);
const handleChange = (event: SelectChangeEvent) => {
setSortBy(event.target.value as string);
};
// search
useEffect(() => {
const newData = data.filter((value: any) => {
if (globalFilter) {
return value.curriculumName.toLowerCase().includes(globalFilter.toLowerCase());
} else {
return value;
}
});
console.log(newData.length);
setCurriculumCard(newData);
}, [globalFilter]);
const PER_PAGE = 6;
const count = Math.ceil(curriculumCard.length / PER_PAGE);
const _DATA = usePagination(curriculumCard, PER_PAGE);
const handleChangePage = (e: any, p: any) => {
setPage(p);
_DATA.jump(p);
};
return (
<MainCard content={false}>
<ScrollX>
</ScrollX>
</MainCard>
<>
<Box sx={{ position: 'relative', marginBottom: 3 }}>
<Stack direction="row" alignItems="center">
<Stack
direction={matchDownSM ? 'column' : 'row'}
sx={{ width: '100%' }}
spacing={1}
justifyContent="space-between"
alignItems="center"
>
{/* @ts-ignore */}
<GlobalFilter preGlobalFilteredRows={data} globalFilter={globalFilter} setGlobalFilter={setGlobalFilter} />
<Stack direction={matchDownSM ? 'column' : 'row'} alignItems="center" spacing={1}>
<FormControl sx={{ m: 1, minWidth: 120 }}>
<Select
value={sortBy}
onChange={handleChange}
displayEmpty
inputProps={{ 'aria-label': 'Without label' }}
renderValue={(selected) => {
if (!selected) {
return <Typography variant="subtitle1">Sort By</Typography>;
}
return <Typography variant="subtitle2">Sort by ({sortBy})</Typography>;
}}
>
{allColumns.map((column) => {
return (
<MenuItem key={column.id} value={column.header}>
{column.header}
</MenuItem>
);
})}
</Select>
</FormControl>
</Stack>
</Stack>
</Stack>
</Box>
<Grid container spacing={3}>
{curriculumCard.length > 0 ? (
_DATA
.currentData()
.sort(function (a: any, b: any) {
if (sortBy === 'Customer Name') return a.fatherName.localeCompare(b.fatherName);
if (sortBy === 'Email') return a.email.localeCompare(b.email);
if (sortBy === 'Contact') return a.contact.localeCompare(b.contact);
if (sortBy === 'Age') return b.age < a.age ? 1 : -1;
if (sortBy === 'Country') return a.country.localeCompare(b.country);
if (sortBy === 'Status') return a.status.localeCompare(b.status);
return a;
})
.map((curriculum: dataProps, index: number) => (
<Slide key={index} direction="up" in={true} timeout={50}>
<Grid item xs={12} sm={6} lg={4}>
<CurriculumCard curriculum={curriculum} />
</Grid>
</Slide>
))
) : (
<EmptyCurriculumCard title={'System have no curriculums yet.'} />
)}
</Grid>
<Stack spacing={2} sx={{ p: 2.5 }} alignItems="flex-end">
<Pagination
count={count}
size="medium"
page={page}
showFirstButton
showLastButton
variant="combined"
color="primary"
onChange={handleChangePage}
/>
</Stack>
</>
)
}
......
export interface dataProps {
_id: number | string | undefined;
curriculumCode: string;
curriculumLevel: number;
curriculumName: string;
curriculumDescription: string;
curriculumImage: string;
tutorials?: tutorialItemProps[];
status?: number;
createdBy?: string;
updatedBy?: string;
createdAt?: Date;
updatedAt?: Date;
}
export interface tutorialItemProps {
_id: number | string | undefined;
tutorialCode: string;
tutorialTitle: string;
tutorialDescription: string;
tutorialImage: string;
status?: number;
createdBy?: string;
updatedBy?: string;
createdAt?: Date;
updatedAt?: Date;
taskItems?: taskItemProps[]
}
export interface taskItemProps {
_id: number | string | undefined;
title: string;
description: string;
howToDo: string;
referenceImage: string;
referenceVideo: string;
}
\ No newline at end of file
......@@ -3,6 +3,7 @@ import { MouseEvent, useMemo, useState } from 'react';
// material-ui
import {
Button,
Dialog,
IconButton,
Stack,
Table,
......@@ -32,7 +33,9 @@ import {
import { DeleteTwoTone, EditTwoTone, EyeTwoTone, PlusOutlined } from '@ant-design/icons';
//types
import AlertTutorialDelete from 'sections/parameters/tutorial-management/AlertTutorialDelete';
import { PopupTransition } from 'components/@extended/Transitions';
import AddEditCurriculum from 'sections/parameters/curriculum-management/AddEditCurriculum';
import AlertCurriculumDelete from 'sections/parameters/curriculum-management/AlertCurriculumDelete';
import { ReactTableProps, curriculumProps, dataProps } from './types/types';
// ==============================|| REACT TABLE ||============================== //
......@@ -154,7 +157,7 @@ const List = () => {
},
{
Header: 'Curriculum Name',
accessor: 'curriculumName'
accessor: 'curriculumTitle'
},
{
Header: 'Status',
......@@ -205,8 +208,8 @@ const List = () => {
color="error"
onClick={(e: MouseEvent<HTMLButtonElement>) => {
e.stopPropagation();
// setTutorialId(row.values.id)
// setOpenAlert(true)
setCurriculumId(row.values._id)
setOpenAlert(true)
}}
>
<DeleteTwoTone twoToneColor={theme.palette.error.main} />
......@@ -232,9 +235,7 @@ const List = () => {
//alert model
const [openAlert, setOpenAlert] = useState(false);
// const [curriculumId, setCurriculumId] = useState<number | null>(null)
const curriculumId : number | null = null
const [curriculumId, setCurriculumId] = useState<number | string | undefined>(undefined)
const handleAlertClose = () => {
setOpenAlert(!openAlert);
......@@ -246,8 +247,21 @@ const List = () => {
<ScrollX>
<ReactTable columns={columns} data={data} handleAddEdit={handleAddEdit} />
</ScrollX>
{/* add / edit curriculum dialog */}
<Dialog
maxWidth="sm"
TransitionComponent={PopupTransition}
keepMounted
fullWidth
onClose={handleAddEdit}
open={addEdit}
sx={{ '& .MuiDialog-paper': { p: 0 }, transition: 'transform 225ms' }}
aria-describedby="alert-dialog-slide-description"
>
<AddEditCurriculum curriculum={curriculum} onCancel={handleAddEdit} />
</Dialog>
{/* alert model */}
{!curriculum && <AlertTutorialDelete title={""} open={openAlert} handleClose={handleAlertClose} deleteId={curriculumId} />}
{!curriculum && <AlertCurriculumDelete title={""} open={openAlert} handleClose={handleAlertClose} deleteId={curriculumId} />}
</MainCard>
</>
)
......
......@@ -2,16 +2,17 @@ import { Column } from 'react-table';
export interface dataProps {
_id: number | string | undefined;
curriculumCode: String;
curriculumLevel: String;
curriculumName: String;
curriculumImage: String;
curriculumCode: string;
curriculumLevel: number;
curriculumName: string;
curriculumDescription: string;
curriculumImage: string;
tutorials: tutorialItemProps[];
status: Number;
createdBy: String;
updatedBy: String;
status: number;
createdBy: string;
updatedBy: string;
createdAt: Date;
updatedAt: Date;
updatedAt: Date;
}
export interface ReactTableProps {
......@@ -22,26 +23,28 @@ export interface ReactTableProps {
export interface curriculumProps {
_id: number | string | undefined;
curriculumCode: String;
curriculumLevel: String;
curriculumName: String;
curriculumImage: String;
tutorials: tutorialItemProps[];
status: Number;
createdBy: String;
updatedBy: String;
curriculumCode: string;
curriculumLevel: number;
curriculumTitle: string;
curriculumDescription: string;
curriculumImage: string;
tutorials: string[];
status: number;
createdBy: string;
updatedBy: string;
createdAt: Date;
updatedAt: Date;
updatedAt: Date;
}
export interface tutorialItemProps {
_id: number | string | undefined;
tutorialCode: String;
tutorialTitle: String;
tutorialImage: String;
status: Number;
createdBy: String;
updatedBy: String;
tutorialCode: string;
tutorialTitle: string;
tutorialDescription: string;
tutorialImage: string;
status: number;
createdBy: string;
updatedBy: string;
createdAt: Date;
updatedAt: Date;
taskItems: taskItemProps[]
......@@ -49,9 +52,9 @@ export interface tutorialItemProps {
export interface taskItemProps {
_id: number | string | undefined;
title: String;
description: String;
howToDo: String;
referenceImage: String;
referenceVideo: String;
title: string;
description: string;
howToDo: string;
referenceImage: string;
referenceVideo: string;
}
\ No newline at end of file
......@@ -3,6 +3,7 @@ import { MouseEvent, useMemo, useState } from 'react';
// material-ui
import {
Button,
Dialog,
IconButton,
Stack,
Table,
......@@ -18,6 +19,7 @@ import {
import { Cell, Column, HeaderGroup, Row, useFilters, useGlobalFilter, usePagination, useTable } from 'react-table';
// project import
import { PopupTransition } from 'components/@extended/Transitions';
import MainCard from 'components/MainCard';
import ScrollX from 'components/ScrollX';
import { CSVExport, EmptyTable, TablePagination } from 'components/third-party/ReactTable';
......@@ -32,6 +34,7 @@ import {
import { DeleteTwoTone, EditTwoTone, EyeTwoTone, PlusOutlined } from '@ant-design/icons';
//types
import AddEditTutorial from 'sections/parameters/tutorial-management/AddEditTutorial';
import AlertTutorialDelete from 'sections/parameters/tutorial-management/AlertTutorialDelete';
import { ReactTableProps, dataProps, tutorialProps } from './types/types';
......@@ -149,7 +152,7 @@ const List = () => {
accessor: 'tutorialCode'
},
{
Header: 'Tutorial Title',
Header: 'Tutorial Name',
accessor: 'tutorialTitle'
},
{
......@@ -201,8 +204,8 @@ const List = () => {
color="error"
onClick={(e: MouseEvent<HTMLButtonElement>) => {
e.stopPropagation();
// setTutorialId(row.values.id)
// setOpenAlert(true)
setTutorialId(row.values._id)
setOpenAlert(true)
}}
>
<DeleteTwoTone twoToneColor={theme.palette.error.main} />
......@@ -228,9 +231,7 @@ const List = () => {
//alert model
const [openAlert, setOpenAlert] = useState(false);
// const [tutorialId, setTutorialId] = useState<number | null>(null)
const tutorialId: number | null = null
const [tutorialId, setTutorialId] = useState<number | string | undefined>(undefined)
const handleAlertClose = () => {
setOpenAlert(!openAlert);
......@@ -242,6 +243,19 @@ const List = () => {
<ScrollX>
<ReactTable columns={columns} data={data} handleAddEdit={handleAddEdit} />
</ScrollX>
{/* add / edit tutorial dialog */}
<Dialog
maxWidth="sm"
TransitionComponent={PopupTransition}
keepMounted
fullWidth
onClose={handleAddEdit}
open={addEdit}
sx={{ '& .MuiDialog-paper': { p: 0 }, transition: 'transform 225ms' }}
aria-describedby="alert-dialog-slide-description"
>
<AddEditTutorial tutorial={tutorial} onCancel={handleAddEdit} />
</Dialog>
{/* alert model */}
{!tutorial && <AlertTutorialDelete title={""} open={openAlert} handleClose={handleAlertClose} deleteId={tutorialId} />}
</MainCard>
......
......@@ -2,12 +2,13 @@ import { Column } from 'react-table';
export interface dataProps {
_id: number | string | undefined;
tutorialCode: String;
tutorialTitle: String;
tutorialImage: String;
status: Number;
createdBy: String;
updatedBy: String;
tutorialCode: string;
tutorialTitle: string;
tutorialDescription: string;
tutorialImage: string;
status: number;
createdBy: string;
updatedBy: string;
createdAt: Date;
updatedAt: Date;
taskItems: taskItemProps[]
......@@ -21,12 +22,13 @@ export interface ReactTableProps {
export interface tutorialProps {
_id: number | string | undefined;
tutorialCode: String;
tutorialTitle: String;
tutorialImage: String;
status: Number;
createdBy: String;
updatedBy: String;
tutorialCode: string;
tutorialTitle: string;
tutorialDescription: string;
tutorialImage: string;
status: number;
createdBy: string;
updatedBy: string;
createdAt: Date;
updatedAt: Date;
taskItems: taskItemProps[]
......@@ -34,9 +36,9 @@ export interface tutorialProps {
export interface taskItemProps {
_id: number | string | undefined;
title: String;
description: String;
howToDo: String;
referenceImage: String;
referenceVideo: String;
title: string;
description: string;
howToDo: string;
referenceImage: string;
referenceVideo: string;
}
\ No newline at end of file
import { useState } from 'react';
// material-ui
import {
Button,
Divider,
Fade,
Grid,
List,
ListItem,
ListItemAvatar,
ListItemText,
Menu,
MenuItem,
Stack,
Typography
} from '@mui/material';
// third-party
import { PDFDownloadLink } from '@react-pdf/renderer';
// project import
import IconButton from 'components/@extended/IconButton';
import MainCard from 'components/MainCard';
// assets
import { MoreOutlined } from '@ant-design/icons';
import Avatar from 'components/@extended/Avatar';
import curriculumLevels from 'data/curriculumLevels';
// types
export interface curriculumCardProps {
_id: number | string | undefined;
curriculumCode: string;
curriculumLevel: number;
curriculumName: string;
curriculumDescription: string;
curriculumImage: string;
tutorials?: tutorialItemProps[];
status?: number;
createdBy?: string;
updatedBy?: string;
createdAt?: Date;
updatedAt?: Date;
}
export interface tutorialItemProps {
_id: number | string | undefined;
tutorialCode: string;
tutorialTitle: string;
tutorialDescription: string;
tutorialImage: string;
status?: number;
createdBy?: string;
updatedBy?: string;
createdAt?: Date;
updatedAt?: Date;
taskItems?: taskItemProps[]
}
export interface taskItemProps {
_id: number | string | undefined;
title: string;
description: string;
howToDo: string;
referenceImage: string;
referenceVideo: string;
}
// ==============================|| CURRICULUM - CARD ||============================== //
const CurriculumCard = ({ curriculum }: { curriculum: curriculumCardProps }) => {
// const [open, setOpen] = useState(false);
// const handleClickOpen = () => {
// setOpen(true);
// };
// const handleClose = () => {
// setOpen(false);
// };
const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);
const openMenu = Boolean(anchorEl);
const handleMenuClick = (event: React.MouseEvent<HTMLElement>) => {
setAnchorEl(event.currentTarget);
};
const handleMenuClose = () => {
setAnchorEl(null);
};
return (
<>
<MainCard sx={{ height: 1, '& .MuiCardContent-root': { height: 1, display: 'flex', flexDirection: 'column' } }}>
<Grid id="print" container spacing={2.25}>
<Grid item xs={12}>
<List sx={{ width: 1, p: 0 }}>
<ListItem
disablePadding
secondaryAction={
<IconButton edge="end" aria-label="comments" color="secondary" onClick={handleMenuClick}>
<MoreOutlined style={{ fontSize: '1.15rem' }} />
</IconButton>
}
>
<ListItemAvatar>
<Avatar alt={curriculum.curriculumName!} src={curriculum.curriculumImage!} />
</ListItemAvatar>
<ListItemText
primary={<Typography variant="subtitle1">{curriculum.curriculumName}</Typography>}
secondary={
<Typography variant="caption" color="secondary">
{curriculumLevels.find(level => level.id === curriculum.curriculumLevel)?.description || ""}
</Typography>
}
/>
</ListItem>
</List>
<Menu
id="fade-menu"
MenuListProps={{
'aria-labelledby': 'fade-button'
}}
anchorEl={anchorEl}
open={openMenu}
onClose={handleMenuClose}
TransitionComponent={Fade}
anchorOrigin={{
vertical: 'bottom',
horizontal: 'right'
}}
transformOrigin={{
vertical: 'top',
horizontal: 'right'
}}
>
<MenuItem sx={{ a: { textDecoration: 'none', color: 'inherit' } }}>
<PDFDownloadLink
document={<></>} fileName={`${curriculum.curriculumCode}-${curriculum.curriculumName}.pdf`}
// document={<ListSmallCard customer={customer} />} fileName={`Customer-${customer.fatherName}.pdf`}
>
Export PDF
</PDFDownloadLink>
</MenuItem>
</Menu>
</Grid>
<Grid item xs={12}>
<Divider />
</Grid>
<Grid item xs={12}>
<Typography>{curriculum.curriculumDescription}</Typography>
</Grid>
{/* <Grid item xs={12}>
<Grid container spacing={1}>
<Grid item xs={6}>
<List sx={{ p: 0, overflow: 'hidden', '& .MuiListItem-root': { px: 0, py: 0.5 } }}>
<ListItem>
<ListItemIcon>
<MailOutlined />
</ListItemIcon>
<ListItemText primary={<Typography color="secondary">{customer.email}</Typography>} />
</ListItem>
<ListItem>
<ListItemIcon>
<PhoneOutlined />
</ListItemIcon>
<ListItemText
primary={
<Typography color="secondary">
<PatternFormat displayType="text" format="+1 (###) ###-####" mask="_" defaultValue={customer.contact} />
</Typography>
}
/>
</ListItem>
</List>
</Grid>
<Grid item xs={6}>
<List sx={{ p: 0, overflow: 'hidden', '& .MuiListItem-root': { px: 0, py: 0.5 } }}>
<ListItem>
<ListItemIcon>
<EnvironmentOutlined />
</ListItemIcon>
<ListItemText primary={<Typography color="secondary">{customer.country}</Typography>} />
</ListItem>
<ListItem>
<ListItemIcon>
<LinkOutlined />
</ListItemIcon>
<ListItemText
primary={
<Link href="https://google.com" target="_blank" sx={{ textTransform: 'lowercase' }}>
https://{customer.firstName}.en
</Link>
}
/>
</ListItem>
</List>
</Grid>
</Grid>
</Grid>
<Grid item xs={12}>
<Box>
<Box
sx={{
display: 'flex',
flexWrap: 'wrap',
listStyle: 'none',
p: 0.5,
m: 0
}}
component="ul"
>
{customer.skills.map((skill: string, index: number) => (
<ListItem disablePadding key={index} sx={{ width: 'auto', pr: 0.75, pb: 0.75 }}>
<Chip color="secondary" variant="outlined" size="small" label={skill} />
</ListItem>
))}
</Box>
</Box>
</Grid> */}
</Grid>
<Stack
direction="row"
className="hideforPDf"
alignItems="center"
spacing={1}
justifyContent="space-between"
sx={{ mt: 'auto', mb: 0, pt: 2.25 }}
>
<Typography variant="caption" color="secondary">
Updated in {curriculum.createdAt?.toLocaleTimeString()}
</Typography>
<Button variant="outlined" size="small" onClick={() => {
// handleClickOpen()
}}>
Preview
</Button>
</Stack>
</MainCard>
{/* edit customer dialog */}
{/* <CustomerPreview customer={customer} open={open} onClose={handleClose} /> */}
</>
);
};
export default CurriculumCard;
// material-ui
import { CardContent, Grid, Skeleton, Stack, Avatar } from '@mui/material';
// project import
import MainCard from 'components/MainCard';
// assets
import { ContactsOutlined } from '@ant-design/icons';
// ===========================|| SKELETON - USER EMPTY CARD ||=========================== //
const UserCard = () => {
return (
<MainCard
border={false}
content={false}
boxShadow
sx={{ boxShadow: `rgba(50, 50, 93, 0.25) 0px 13px 27px -5px, rgba(0, 0, 0, 0.3) 0px 8px 16px -8px`, borderRadius: 2 }}
>
<CardContent sx={{ p: 2 }}>
<Grid container spacing={2}>
<Grid item xs={12}>
<Stack flexDirection="row" alignItems="center">
<Avatar>
<ContactsOutlined style={{ visibility: 'inherit' }} />
</Avatar>
<Stack sx={{ width: '100%', pl: 2.5 }}>
<Skeleton animation={false} height={20} width="80%" />
<Skeleton animation={false} height={20} width="40%" />
</Stack>
</Stack>
</Grid>
<Grid item xs={12}>
<Skeleton animation={false} height={20} width={45} />
<Skeleton animation={false} height={20} />
<Stack direction="row" alignItems="center" spacing={1}>
<Skeleton animation={false} height={20} width={90} />
<Skeleton animation={false} height={20} width={38} />
</Stack>
</Grid>
<Grid item xs={12}>
<Stack direction="row" justifyContent="space-between" alignItems="center">
<Grid container spacing={1}>
<Grid item>
<Skeleton animation={false} height={20} width={40} />
</Grid>
<Grid item>
<Skeleton animation={false} height={17} width={20} />
</Grid>
</Grid>
<Skeleton animation={false} height={32} width={47} />
</Stack>
</Grid>
</Grid>
</CardContent>
</MainCard>
);
};
export default UserCard;
// material-ui
import { Box, Grid, Stack, Typography } from '@mui/material';
// project import
import CurriculumCard from './CurriculumCard';
interface Props {
title: string;
}
// ==============================|| EMPTY STATE ||============================== //
const EmptyCurriculumCard = ({ title }: Props) => {
return (
<Grid container spacing={3}>
<Grid item xs={12}>
<Box
sx={{
p: { xs: 2.5, sm: 6 },
height: `calc(100vh - 192px)`,
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
bgcolor: 'transparent'
}}
>
<Grid container direction="column" justifyContent="center" alignItems="center">
<Grid item>
<Box sx={{ ml: -9, mb: { xs: -8, sm: -5 } }}>
<Box sx={{ position: 'relative' }}>
<CurriculumCard />
</Box>
<Box sx={{ position: 'relative', top: -120, left: 72 }}>
<CurriculumCard />
</Box>
</Box>
</Grid>
<Grid item>
<Stack spacing={1}>
<Typography align="center" variant="h4">
{title}
</Typography>
</Stack>
</Grid>
</Grid>
</Box>
</Grid>
</Grid>
);
};
export default EmptyCurriculumCard;
......@@ -13,7 +13,7 @@ interface Props {
title: string;
open: boolean;
handleClose: (status: boolean) => void;
deleteId: number | null;
deleteId: number | string | undefined;
}
// ==============================|| Curriculum - DELETE ||============================== //
......
......@@ -13,7 +13,7 @@ interface Props {
title: string;
open: boolean;
handleClose: (status: boolean) => void;
deleteId: number | null;
deleteId: number | string | undefined;
}
// ==============================|| Tutorial - DELETE ||============================== //
......
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