update,
This commit is contained in:
5
tsc1877/.gitignore
vendored
Normal file
5
tsc1877/.gitignore
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
.env
|
||||
**/volumes
|
||||
**/*.zip
|
||||
**/*.7z
|
||||
**/draft*
|
BIN
tsc1877/ConEmu64_jwEAbC5dbe.png
(Stored with Git LFS)
Normal file
BIN
tsc1877/ConEmu64_jwEAbC5dbe.png
(Stored with Git LFS)
Normal file
Binary file not shown.
7
tsc1877/gitUpdate.bat
Normal file
7
tsc1877/gitUpdate.bat
Normal file
@@ -0,0 +1,7 @@
|
||||
git status .
|
||||
|
||||
@pause
|
||||
|
||||
git add .
|
||||
git commit -m"update tsc1877,"
|
||||
start git push
|
20
tsc1877/meta.md
Normal file
20
tsc1877/meta.md
Normal file
@@ -0,0 +1,20 @@
|
||||
---
|
||||
tags: [aws, react, nextjs, javascript]
|
||||
---
|
||||
|
||||
# tsc1877
|
||||
|
||||
## Balance history
|
||||
|
||||
### quotation
|
||||
|
||||
- phase 2 HKD 400
|
||||
- phase 3 HKD 400
|
||||
- phase 4 HKD 400
|
||||
- phase 5 HKD 400
|
||||
- login page HKD 200 (variation order)
|
||||
|
||||
### payment history
|
||||
|
||||
HKD 200 deposit paid
|
||||
HKD 800 phase2 & 3 paid
|
18
tsc1877/task1/.editorconfig
Normal file
18
tsc1877/task1/.editorconfig
Normal file
@@ -0,0 +1,18 @@
|
||||
# Editor configuration, see http://editorconfig.org
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
end_of_line = lf
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[*.md]
|
||||
max_line_length = off
|
||||
trim_trailing_whitespace = false
|
||||
|
||||
[*.yml]
|
||||
[*.{yml,yaml}]
|
||||
indent_size = 2
|
17
tsc1877/task1/.prettierrc.js
Normal file
17
tsc1877/task1/.prettierrc.js
Normal file
@@ -0,0 +1,17 @@
|
||||
module.exports = {
|
||||
arrowParens: 'avoid',
|
||||
bracketSpacing: true,
|
||||
htmlWhitespaceSensitivity: 'css',
|
||||
insertPragma: false,
|
||||
bracketSameLine: false,
|
||||
jsxSingleQuote: true,
|
||||
printWidth: 120,
|
||||
proseWrap: 'preserve',
|
||||
quoteProps: 'as-needed',
|
||||
requirePragma: false,
|
||||
semi: false,
|
||||
singleQuote: true,
|
||||
tabWidth: 2,
|
||||
trailingComma: 'none',
|
||||
useTabs: false
|
||||
}
|
327
tsc1877/task1/NOTES.md
Normal file
327
tsc1877/task1/NOTES.md
Normal file
@@ -0,0 +1,327 @@
|
||||
1. 你想我做? (做完比番你 / $)
|
||||
2. 你想我做完話你知點做? (花時間 / $$)
|
||||
3. 你想我經你隻手做? (花花花時間 / $$$)
|
||||
|
||||
有冇咩取向??
|
||||
|
||||
我唔係想同你打心理戰,但係我想知一知呢樣野先
|
||||
10 個識等如全部識晒,咁你會比幾多個識比你自己?
|
||||
|
||||
我諗我會報 HKD 400 / phase
|
||||
|
||||
你用 mac ?
|
||||
留一個聯絡方式?
|
||||
|
||||
ttps://t.me/louislabs/
|
||||
|
||||
留一留個 ec2 個登入方法?
|
||||
|
||||
thanks
|
||||
|
||||
Q: 我俾 pem key 同 elastic ip 你?
|
||||
A: 可以呀,你經果頁 upload 比我 OK ?
|
||||
|
||||
揸定主意,用 nextjs 啦嘛
|
||||
|
||||
|
||||
© 2024, Made with ❤️ by ThemeSelection
|
||||
會唔會可以再簡單小小?例如唔洗右上嗰啲function?
|
||||
|
||||
|
||||
### references
|
||||
https://themeselection.com/item/materio-free-mui-nextjs-admin-template/
|
||||
|
||||
---
|
||||
|
||||
51.21.113.230
|
||||
|
||||
---
|
||||
|
||||
## Phase 2
|
||||
|
||||
### ASSIGNMENT MARKING CHECKLIST V1
|
||||
|
||||
#### PHASE 2A: SECURE SERVER SETUP (DEADLINE FEB.17, 2024) (SUBTOTAL: 5')
|
||||
|
||||
In this phase, you are required to set up a secure server for later development. Some guidance will be given in the tutorial.
|
||||
|
||||
1. Instantiate a free Virtual Cloud Machine (Amazon EC2 recommended or other free VPS) **\_** / 1'
|
||||
|
||||
- [ ] Details of the Free Usage Tier: http://aws.amazon.com/free
|
||||
- [ ] You can apply for the education coupon on AWS
|
||||
- [ ] With a Linux distribution, install only Ngnix, NodeJS and SQLite (or MySQL)
|
||||
- [ ] To minimize the attack surfaces, always install only what you need
|
||||
|
||||
1. Apply necessary security configurations **\_** / 2'
|
||||
|
||||
- [ ] Apply proper firewall settings to your VM: block all ports except 22, 80 and 443 only
|
||||
- [ ] Apply proper updates for the server software packages in a regular manner
|
||||
- [ ] Hide the versions of OS, Ngnix, and NodeJS in HTTP response headers
|
||||
|
||||
1. Configure the VM so that your website is accessible at http://sxx.ierg4210.ie.cuhk.edu.hk **\_** / 2'
|
||||
|
||||
- [ ] Apply for an elastic public IP, and ALWAYS associate it with the instantiated VM
|
||||
- [ ] Submit your elastic IP through the provided Google Form link1 before 5pm, Feb 17, 2024
|
||||
- [ ] TAs will then assign you a domain name and configure the DNS mapping for you
|
||||
- [ ] Upload all your pages to the server. They should then be accessible through:
|
||||
- [ ] http://[your-own-public-IP], or
|
||||
- [ ] http://sxx.ierg4210.ie.cuhk.edu.hk
|
||||
|
||||
#### PHASE 2B: DATA PRESENTATION & MANAGEMENT (DEADLINE FEB. 25, 2024) (SUBTOTAL: 20')
|
||||
|
||||
In this phase, you will implement the core functions of the website mainly with NodeJS and SQL.
|
||||
|
||||
1. SQL: Create a database with the following structures (to be covered in the tutorial) **\_** / 1'
|
||||
|
||||
- [x] A table for `categories`
|
||||
- [x] Required columns:
|
||||
-[ ] [x] `cid` (primary key),
|
||||
-[ ] [x] `name`
|
||||
- [x] Data: at least 3 `categories` of your choice
|
||||
|
||||
- [x] A table for `products`
|
||||
- [x] Required columns:
|
||||
-[ ] [x] `pid (primary key)`,
|
||||
-[ ] [x] `cid`,
|
||||
-[ ] [x] `name`,
|
||||
-[ ] [x] `price`,
|
||||
-[ ] [x] `description`
|
||||
- [x] Data: at least 3 products for each category
|
||||
|
||||
1. HTML, NodeJS & SQL: Create an `admin panel`
|
||||
|
||||
- [x] Design several HTML forms to manage(you can `insert`, `update` and `delete` information, `CRUD`) products in DB **\_** / 5'
|
||||
-[ ] [x] `insert`
|
||||
-[ ] [x] `update`
|
||||
-[ ] [x] `delete`
|
||||
-[ ] [x] Dropdown menu to select `cid` according to its name
|
||||
-[ ] [x] Input fields for inputting
|
||||
-[ ] [x] `name`,
|
||||
-[ ] [x] `price`
|
||||
-[ ] [x] Textarea for inputting `description`
|
||||
|
||||
|
||||
- [x] Design several HTML forms to manage `categories` in DB **\_** / 2'
|
||||
-[ ] [x] `insert`
|
||||
-[ ] [x] `update`
|
||||
-[ ] [x] `delete`
|
||||
|
||||
2. HTML, NodeJS, SQL: Update the ***main page*** created in Phase 1
|
||||
|
||||
- [x] Populate the `category` list from DB **\_** / 1'
|
||||
- [x] Based on the `category` selected by the user, populate the corresponding product list from DB **\_** / 3'
|
||||
-[ ] [x] The `cid=[x]` is reflected as a query string in the URL
|
||||
-[ ] [x] 你想用邊種? 新做法我可以留番個註解比你 -> 新
|
||||
|
||||
3. HTML, NodeJS & SQL: Update the `product details` page created in Phase 1 **\_** / 2'
|
||||
|
||||
- [x] Display the details of a product based on its DB record
|
||||
- [?] Display the inventory of a product based on its DB record
|
||||
|
||||
4. Support of automatic image resizing for product images **\_** / 3'
|
||||
5. Supporting HTML5 Drag-and-drop file selection in the admin panel **\_** / 2'
|
||||
- [x] limit to upload jpg file
|
||||
|
||||
- [x] File field for uploading an image (format: jpg/gif/png, size: <=5MB)
|
||||
- [/] For the file uploaded, store it with its name. **\_** / 1'
|
||||
-[ ] default to `my_path/image.jpg`
|
||||
|
||||
- [?] When a large image is uploaded, the server will resize it and show a thumbnail image in the panel
|
||||
- [x] On the main page, display thumbnails. On the product description page, display the larger image
|
||||
|
||||
- [?] Create a dropping area that takes an image
|
||||
- [?] Display a thumbnail (i.e. smaller width and height) if the dropped file is an image; reject it otherwise
|
||||
|
||||
### !!!CSRF
|
||||
|
||||
---
|
||||
|
||||
## PHASE 3
|
||||
|
||||
### AJAX SHOPPING LIST (DEADLINE: MAR 10, 2024) (SUBTOTAL: 13')
|
||||
|
||||
In this phase, you will implement the shopping list, which allows users to shop around your products. This phase is designed to let you practise Javascript programming.
|
||||
|
||||
1. JS: Dynamically update# the `shopping list`
|
||||
|
||||
- [x] When the `addToCart` button of a product is clicked, add it to the shopping list **\_** / 1'
|
||||
-[ ] [x] Adding the same product twice will display only one row of record
|
||||
|
||||
- Once a product is added,
|
||||
-[ ] Users are allowed to
|
||||
-[ ] [x] update its `quantity` and
|
||||
-[ ] [x] delete it with a number input, or
|
||||
-[ ] [x] two buttons for increment and decrement
|
||||
-[ ] [x] Store its
|
||||
-[ ] [x] `pid` and
|
||||
-[ ] [x] `quantity` in the browser's `localStorage` **\_** / 2'
|
||||
-[ ] [x] Get the
|
||||
-[ ] [x] `name` and
|
||||
-[ ] [x] `price` from the server (with `pid` as input) **\_** / 3'
|
||||
-[ ] [x] Calculate and display the `total amount` at the client-side **\_** / 1'
|
||||
|
||||
- [x] Once the page is reloaded, the shopping list is restored **\_** / 2'
|
||||
-[ ] Page reloads when
|
||||
-[ ] [x] users browse another category or
|
||||
-[ ] [x] visit the product detail page
|
||||
-[ ] [x] Populate and retrieve the stored products from the `localStorage`
|
||||
|
||||
- [?] Supporting infinite scroll when browsing products in the main page **\_** / 3'
|
||||
|
||||
<sub>#The whole process of shopping list management must be done without a page load</sub>
|
||||
|
||||
---
|
||||
|
||||
|
||||
|
||||
- aws setup swap file
|
||||
- https://repost.aws/knowledge-center/ec2-memory-swap-file
|
||||
|
||||
|
||||
---
|
||||
|
||||
## phase 5
|
||||
|
||||
### Paypal Sandbox Accounts
|
||||
|
||||
1. Sign up at https://developer.paypal.com/dashboard/ : ______ / 1'
|
||||
a. Create two sandbox accounts – a merchant account and a buyer account:
|
||||
i. A merchant account – Email and Password
|
||||
sb-j4nbw29912003@business.example.com
|
||||
X<LqO7Sb
|
||||
|
||||
ii. A buyer account – Email and Password
|
||||
sb-b00gb30304504@personal.example.com
|
||||
4s@0f>IE
|
||||
|
||||
b. Create a sandbox application linked to the merchant account:
|
||||
i. an application – Client ID
|
||||
https://developer.paypal.com/dashboard/accounts/edit/4829534511909691981?accountName=sb-j4nbw29912003@business.example.com
|
||||
helloworld
|
||||
Client ID
|
||||
AQT5-eAKNK7IhAhBGlbHBu_9jBx74ZLCfEioKUWQMXMuMmLcnffmpoUz_z-ewOuKZmpSlDk74UtlH58O
|
||||
Secret key 1
|
||||
EMtwOzHACol7Tx8NHOa3eV3TPu2AerZEunJ3MBZfYYcxPeUDy-TNLqqcdL0UDQsrHMpQKeCRPcjKnwNy
|
||||
|
||||
#### Paypal Integration - Front End
|
||||
Ref:
|
||||
- https://developer.paypal.com/community/blog/how-to-add-paypal-checkout-payments-to-your-react-app/
|
||||
|
||||
2. Create a checkout button via PayPal standard checkout APIs: ______ / 1'
|
||||
a [x] Include the PayPal JavaScript SDK
|
||||
b [x] Set up a container element for the button
|
||||
c [x] Render the button by paypal.Buttons().render()
|
||||
3. [x] When the checkout button is clicked, `createOrder()` is called: ______ / 3'
|
||||
a [x] every individual product (or any other data) to server.
|
||||
-[x] `name`
|
||||
-[x] `quantity`
|
||||
b [x] It waits for server to generate a JSON string named `orderDetails`.
|
||||
-[ ] refer backend `6.`
|
||||
c [x] It submits the order now to PayPal using the actions.order.create() function.
|
||||
4 [x] After the buyer has completed the payment, `onApprove()` is called: ______ / 2'
|
||||
a [x] It passes the `orderDetails` to server.
|
||||
b [x] It clears the shopping cart.
|
||||
5 [x] If the buyer cancels the payments, `onCancel()` is called: ______ / 1'
|
||||
a [x] It passes necessary information to server.
|
||||
|
||||
|
||||
#### Paypal Integration - Back End
|
||||
|
||||
6. Server follows the following steps to generate the `orderDetails`: ______ / 5'
|
||||
a. server generates a digest that is the hash from a string composed of at least:
|
||||
-[x] of each selected product
|
||||
-[x] `name`
|
||||
-[x] `quantity`
|
||||
-[x] The `price` of each selected product gathered from DB,
|
||||
-[x] The `total price` of all selected products,
|
||||
-[x] `Currency code`,
|
||||
-[x] Merchant’s `email address`, and
|
||||
-[x] A `random salt`
|
||||
b.[x] server puts the generated digest in the `custom_id` of an order.
|
||||
c.[x] server generates an `UUID`, and puts it in the `invoice_id` of an order.
|
||||
d.[x] server generates other necessary fields of an order, including at least:
|
||||
-[x] `amount` - the `total price` and `currency code`
|
||||
-[x] `items` - the `name`, `quantity`, `price` of each selected item
|
||||
|
||||
7. Server follows the following steps to insert and update the DB orders table: ______ / 3'
|
||||
a. When `createOrder()` is called, it inserts a new entry:
|
||||
-[x] `UUID` - TEXT (Primary Key)
|
||||
- [x] custom_id
|
||||
- [x] invoice_id
|
||||
-[x] `username` - TEXT `customer's username`
|
||||
-[x] `digest` - TEXT, `custom_id`
|
||||
-[x] `salt` - TEXT
|
||||
b. [x] When `onApprove()` is called, it updates the corresponding entry:
|
||||
-[] `orderDetails` - TEXT
|
||||
c. [x] When `onCancel()` is called, it deletes the corresponding entry.
|
||||
|
||||
#### Miscellaneous Changes
|
||||
|
||||
8. [x] Display the DB orders table in the admin panel: product list, payment status…etc. ______ / 2'
|
||||
9. [x] Let members check the most recent five orders in the member portal . ______ / 2'
|
||||
|
||||
|
||||
### signal flow
|
||||
|
||||
#### Notes version:
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
actor Client
|
||||
|
||||
Note left of Client: checkout button is clicked
|
||||
Note left of Client: `createOrder() is called
|
||||
|
||||
Client->>Server: fetch("/my-server/get-order-details"...
|
||||
|
||||
Note over Server: generate `orderDetails`
|
||||
Server->>Client: return json `orderDetails`
|
||||
|
||||
Note over Client: purchase_units: [amount, itesm, custom_id, invoice_id]
|
||||
|
||||
Paypal-->>Client: send payment page
|
||||
Note over Client: Client proceed payment
|
||||
Client-->>Paypal: client approve payment
|
||||
|
||||
Note over Client: When `onApprove()` is called
|
||||
Client->>Server: fetch("/my-server/save-order"...
|
||||
Note over Server: it `update` the corresponding entry
|
||||
|
||||
Note over Client: When `onCancel()` is called
|
||||
Client->>Server: fetch("/my-server/cancel-order"...
|
||||
Note over Server: it `deletes` the corresponding entry
|
||||
```
|
||||
|
||||
|
||||
#### My version:
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
actor Client
|
||||
|
||||
Note left of Client: checkout button is clicked
|
||||
Note left of Client: createOrder() is called
|
||||
|
||||
Client->>Server: fetch("/my-server/get-order-details"...
|
||||
|
||||
Note over Server: generate `orderDetails`
|
||||
Server->>Client: return json `orderDetails`
|
||||
|
||||
Note over Client: purchase_units: [amount, itesm, custom_id, invoice_id]
|
||||
|
||||
Paypal-->>Client: send payment page
|
||||
Note over Client: Client proceed payment
|
||||
Client-->>Paypal: client approve payment
|
||||
|
||||
Paypal->>Server: event_type: CHECKOUT.ORDER.APPROVED
|
||||
Note left of Paypal: with (resources.id + resources.status)
|
||||
|
||||
Note over Client: When `onApprove()` is called
|
||||
Client->>Server: fetch("/my-server/save-order"...
|
||||
Note right of Client: with resources.id
|
||||
|
||||
Note over Server: receive 2 id, found match and stastus "approved"
|
||||
Note over Server: it `update` the corresponding entry
|
||||
|
||||
Note over Client: When `onCancel()` is called
|
||||
Client->>Server: fetch("/my-server/cancel-order"...
|
||||
Note over Server: it `deletes` the corresponding entry
|
||||
```
|
1
tsc1877/task1/_credentials/notes.md
Normal file
1
tsc1877/task1/_credentials/notes.md
Normal file
@@ -0,0 +1 @@
|
||||
13.50.75.106
|
27
tsc1877/task1/_credentials/shopping.pem
Normal file
27
tsc1877/task1/_credentials/shopping.pem
Normal file
@@ -0,0 +1,27 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEpgIBAAKCAQEA60pfYaPm/QVZAq2VRMJRP+YmvHseni8TlvB22Cy5c2lY5Npq
|
||||
Pt432WzmgS2I0SeGUGZbMSf2G6rvrSQP+s9FaQxkqS2JrZI43StO0zu2ogTOD605
|
||||
1XZvQSnVljodTLJrLcYmNa7h4Fj2Avr1//Lsm83w8WQlycnz4u772MsiR7L57miX
|
||||
vSJfaVyDeEEZRb0Ovd3qeFmGfgcPIyZPoCof7BP0uK2gywcHYuOcEn1K7yEl/4ja
|
||||
mXmJL5WWjchvNfOXFLzcQitDhtd6gGcnO5Zxdyby1r2GtQLMXErN5Imsb+V0iwhh
|
||||
lYT2WzSiOF6YpZudG/aCplLWutgINsnJek0FUwIDAQABAoIBAQCt4kPFE+zUFoym
|
||||
dwP2UajcEUmVR2PkQSQ4CzO5JKxVB4jDcErOdUlO7LUYyD7xW0Vey5YfKMovvk7s
|
||||
ZNdOYrmIHbmScW3rEUHm6WeSofGhoO1sFnfEMoeb37/SCta2ZLDiniqEx95z/yqo
|
||||
HzGH2s5TgonKy1lF3HLZxgXnPI/z7XzZrhVOq7LCechLToB9isJtJDH0kr/av2f0
|
||||
VRdbwfREgQ7OsmehaP4sCPHeRwe4w8v03a7YUYLIRxPrTKiLW/Fw9RUOnTS13bj5
|
||||
HirWIHHXAVXFdI1dHwZ0ViUITkk/twZe48WUaHcC9zdWqNoq+Ln5bQN5MuFO0A30
|
||||
DBrhIpCpAoGBAP6WTM0pqk7n+IvOpWBmFatWq6Oe9Vdl5ua4AKInDAduDK5T9Vvq
|
||||
+dWk+IKbvVi5/faO5g2c7MIq4oXDgu1ngawuMsH/HBs08SmRUrDVTuDJrUEh8BGe
|
||||
h+Qnsx+WV4kBNWiT89QiX7Z/2UMbF73HQ00IOXqZHA9OFR8iwaVcGjrtAoGBAOyY
|
||||
qESmRSEw+hzmRHvJgXKzR7LxJuOnn9mp6KVVgaf1VZ4FMOroui9yn6W0973ROFL4
|
||||
z+ZB2STcZwO7iY+HI5MfS0WfK77x3MQNDICm8rGQBdV2/Y1vbM1IoJMedEOnWTKe
|
||||
nRK7WkHMuZuaoVtXsDE9Y7BIQLqtb0g4LhkFqPk/AoGBAI2aQ7WJizTASbpZghqQ
|
||||
LVVTq7wiWgv2neuORKvsVAB98Ye1Iy+xDq0KST88KKEFMoDFEqhXtEh7WetUx6oM
|
||||
fE+skobcwmFPnSOltPyuaGUXR8qGeeUS7Dq26iaTlLSbe31jbad8RwhXLBzrINVp
|
||||
08Ew5eeO6dCJea4LwvGavOwxAoGBAI2t2M3LN4hpuMzHg2kRQOg7vYrFaAFZppqE
|
||||
aaFgM9UtT8jh2OpC1QOGw11KojRT7kOZZX3AHtU4+qM8kWKWjVITolKdv2eHlCj+
|
||||
m2cLEjgMQ8IRkEI64E+J10ZiLUM6Gmr6mprWAHV4sAkjLs7xErxZw7GTgteG9iWs
|
||||
JsarIgWnAoGBALSsZD5Ib4vIKp40AHe/Nu0+ZXzFzqFbxmW5oVDvTE3kp0Nvij5a
|
||||
GPJAqvqyF0LizCwqEO08gyY13/NpsVJ5J+TMdP6eGIIT5ewGGspslrTeuxAq20Wx
|
||||
zGn6ytrECrdtYVZkPpKnXWzsx4NooywTNhTKCVjyvOpH+/7GtdPcH9/c
|
||||
-----END RSA PRIVATE KEY-----
|
42
tsc1877/task1/_poc/sequelize/helloworld.js
Normal file
42
tsc1877/task1/_poc/sequelize/helloworld.js
Normal file
@@ -0,0 +1,42 @@
|
||||
const { Sequelize } = require('sequelize')
|
||||
|
||||
const sequelize = new Sequelize('app_db', 'db_user', 'db_user_pass', {
|
||||
host: 'localhost',
|
||||
port: 6033,
|
||||
dialect: 'mysql'
|
||||
})
|
||||
|
||||
const User = sequelize.define(
|
||||
'User',
|
||||
{
|
||||
firstName: {
|
||||
type: Sequelize.STRING,
|
||||
allowNull: false
|
||||
},
|
||||
lastName: {
|
||||
type: Sequelize.STRING,
|
||||
allowNull: false
|
||||
}
|
||||
},
|
||||
{ timestamps: false }
|
||||
)
|
||||
|
||||
;(async () => {
|
||||
try {
|
||||
await sequelize.authenticate()
|
||||
console.log('Connection has been established successfully.')
|
||||
|
||||
// create table
|
||||
await sequelize.sync()
|
||||
|
||||
const user = await User.create({ firstName: 'John', lastName: 'Doe' })
|
||||
console.log('Created user: ', user)
|
||||
|
||||
const users = await User.findAll()
|
||||
console.log('Found all users: ', users)
|
||||
|
||||
await sequelize.close()
|
||||
} catch (error) {
|
||||
console.error('Unable to connect to the database:', error)
|
||||
}
|
||||
})()
|
17
tsc1877/task1/_poc/sequelize/package.json
Normal file
17
tsc1877/task1/_poc/sequelize/package.json
Normal file
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"name": "sequelize",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "helloworld.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"mysql2": "^3.9.3",
|
||||
"sequelize": "^6.37.1",
|
||||
"sqlite3": "^5.1.7"
|
||||
}
|
||||
}
|
1043
tsc1877/task1/_poc/sequelize/yarn.lock
Normal file
1043
tsc1877/task1/_poc/sequelize/yarn.lock
Normal file
File diff suppressed because it is too large
Load Diff
BIN
tsc1877/task1/_ref/2022/IERG4210-22S-Phase4.pdf
Normal file
BIN
tsc1877/task1/_ref/2022/IERG4210-22S-Phase4.pdf
Normal file
Binary file not shown.
BIN
tsc1877/task1/_ref/2022/IERG4210-22S-Phase5-Updated.pdf
Normal file
BIN
tsc1877/task1/_ref/2022/IERG4210-22S-Phase5-Updated.pdf
Normal file
Binary file not shown.
BIN
tsc1877/task1/_ref/2022/IERG4210-22S-Phase5.pdf
Normal file
BIN
tsc1877/task1/_ref/2022/IERG4210-22S-Phase5.pdf
Normal file
Binary file not shown.
BIN
tsc1877/task1/_ref/2024/IERG4210-24S-Phase1.pdf
Normal file
BIN
tsc1877/task1/_ref/2024/IERG4210-24S-Phase1.pdf
Normal file
Binary file not shown.
BIN
tsc1877/task1/_ref/2024/IERG4210-24S-Phase2_v2.pdf
Normal file
BIN
tsc1877/task1/_ref/2024/IERG4210-24S-Phase2_v2.pdf
Normal file
Binary file not shown.
BIN
tsc1877/task1/_ref/2024/IERG4210-24S-Phase3.pdf
Normal file
BIN
tsc1877/task1/_ref/2024/IERG4210-24S-Phase3.pdf
Normal file
Binary file not shown.
BIN
tsc1877/task1/_ref/2024/IERG4210-24S-Phase4.pdf
Normal file
BIN
tsc1877/task1/_ref/2024/IERG4210-24S-Phase4.pdf
Normal file
Binary file not shown.
BIN
tsc1877/task1/_ref/2024/IERG4210-24S-Phase5.pdf
Normal file
BIN
tsc1877/task1/_ref/2024/IERG4210-24S-Phase5.pdf
Normal file
Binary file not shown.
BIN
tsc1877/task1/_ref/2024/Tutorial 3.pdf
Normal file
BIN
tsc1877/task1/_ref/2024/Tutorial 3.pdf
Normal file
Binary file not shown.
BIN
tsc1877/task1/_ref/2024/Tutorial 4.pdf
Normal file
BIN
tsc1877/task1/_ref/2024/Tutorial 4.pdf
Normal file
Binary file not shown.
BIN
tsc1877/task1/_ref/2024/Tutorial 5.pdf
Normal file
BIN
tsc1877/task1/_ref/2024/Tutorial 5.pdf
Normal file
Binary file not shown.
BIN
tsc1877/task1/_ref/2024/Tutorial 6.pdf
Normal file
BIN
tsc1877/task1/_ref/2024/Tutorial 6.pdf
Normal file
Binary file not shown.
BIN
tsc1877/task1/_ref/2024/Tutorial 7.pdf
Normal file
BIN
tsc1877/task1/_ref/2024/Tutorial 7.pdf
Normal file
Binary file not shown.
BIN
tsc1877/task1/_ref/2024/Tutorial 8.pdf
Normal file
BIN
tsc1877/task1/_ref/2024/Tutorial 8.pdf
Normal file
Binary file not shown.
BIN
tsc1877/task1/_ref/2024/Tutorial 9.pdf
Normal file
BIN
tsc1877/task1/_ref/2024/Tutorial 9.pdf
Normal file
Binary file not shown.
BIN
tsc1877/task1/_ref/85fd7f2e-6c8e-4bfc-a9ec-12666cc02e23__2_en.png
(Stored with Git LFS)
Normal file
BIN
tsc1877/task1/_ref/85fd7f2e-6c8e-4bfc-a9ec-12666cc02e23__2_en.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
tsc1877/task1/_ref/IERG4210 2024 Spring Tutorial 2.pptx
Normal file
BIN
tsc1877/task1/_ref/IERG4210 2024 Spring Tutorial 2.pptx
Normal file
Binary file not shown.
BIN
tsc1877/task1/_ref/IERG4210-24S-Phase1/0.png
(Stored with Git LFS)
Normal file
BIN
tsc1877/task1/_ref/IERG4210-24S-Phase1/0.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
tsc1877/task1/_ref/IERG4210-24S-Phase1/1.png
(Stored with Git LFS)
Normal file
BIN
tsc1877/task1/_ref/IERG4210-24S-Phase1/1.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
tsc1877/task1/_ref/IERG4210-24S-Phase1/2.png
(Stored with Git LFS)
Normal file
BIN
tsc1877/task1/_ref/IERG4210-24S-Phase1/2.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
tsc1877/task1/_ref/IERG4210-24S-Phase1/3.png
(Stored with Git LFS)
Normal file
BIN
tsc1877/task1/_ref/IERG4210-24S-Phase1/3.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
tsc1877/task1/_ref/chrome_XeuGI0DOuj.png
(Stored with Git LFS)
Normal file
BIN
tsc1877/task1/_ref/chrome_XeuGI0DOuj.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
tsc1877/task1/_ref/old_project/cart.db
Normal file
BIN
tsc1877/task1/_ref/old_project/cart.db
Normal file
Binary file not shown.
78
tsc1877/task1/_ref/old_project/form.html
Normal file
78
tsc1877/task1/_ref/old_project/form.html
Normal file
@@ -0,0 +1,78 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>IERG4210 Admin Panel</title>
|
||||
<style>
|
||||
#drop-area {
|
||||
width: 300px;
|
||||
height: 200px;
|
||||
border: 2px dashed #ccc;
|
||||
border-radius: 5px;
|
||||
text-align: center;
|
||||
font-family: Arial, sans-serif;
|
||||
margin: 0 auto;
|
||||
margin-top: 20px;
|
||||
}
|
||||
#drop-area.highlight {
|
||||
background-color: #f1f1f1;
|
||||
}
|
||||
#drop-area .message {
|
||||
margin: 80px auto;
|
||||
font-size: 18px;
|
||||
color: #888;
|
||||
}
|
||||
#thumbnail {
|
||||
max-width: 200px;
|
||||
max-height: 200px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>IERG4210 Admin Panel</h1>
|
||||
<h1>Add Category</h1>
|
||||
<form action="/addCategory" method="POST">
|
||||
<label for="categoryName">Category Name:</label>
|
||||
<input type="text" id="categoryName" name="categoryName" required>
|
||||
<button type="submit">Add Category</button>
|
||||
</form>
|
||||
|
||||
<h1>Add Product</h1>
|
||||
<form action="/addProduct" method="POST">
|
||||
<label for="productName">Product Name:</label>
|
||||
<input type="text" id="productName" name="productName" required>
|
||||
|
||||
<label for="category">Category:</label>
|
||||
<select id="category" name="category" required>
|
||||
<option value="" selected disabled>Select a category</option>
|
||||
<script>
|
||||
// Fetch categories from the server and populate the dropdown options
|
||||
fetch('/categories')
|
||||
.then(response => response.json())
|
||||
.then(categories => {
|
||||
const categorySelect = document.getElementById('category');
|
||||
categories.forEach(category => {
|
||||
const option = document.createElement('option');
|
||||
option.value = category.catid;
|
||||
option.textContent = category.name;
|
||||
categorySelect.appendChild(option);
|
||||
});
|
||||
})
|
||||
.catch(error => console.error(error));
|
||||
</script>
|
||||
</select>
|
||||
|
||||
<label for="price">Price:</label>
|
||||
<input type="number" id="price" name="price" required>
|
||||
|
||||
<label for="description">Description:</label>
|
||||
<textarea id="description" name="description" required></textarea>
|
||||
|
||||
<label for="image">Image:</label>
|
||||
<input type="file" id="image" name="image" accept="image/*" required>
|
||||
|
||||
<button type="submit">Add Product</button>
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
85
tsc1877/task1/_ref/old_project/server.js
Normal file
85
tsc1877/task1/_ref/old_project/server.js
Normal file
@@ -0,0 +1,85 @@
|
||||
// Import the 'path' module
|
||||
const path = require("path");
|
||||
const express = require("express");
|
||||
const sqlite3 = require("sqlite3").verbose();
|
||||
|
||||
const app = express();
|
||||
const db = new sqlite3.Database("cart.db");
|
||||
|
||||
// Use middleware to parse the request body
|
||||
app.use(express.urlencoded({ extended: true }));
|
||||
|
||||
app.get("/", (req, res) => {
|
||||
res.sendFile(path.join(__dirname, "form.html"));
|
||||
});
|
||||
|
||||
app.get("/categories", (req, res) => {
|
||||
const selectCategoriesQuery = `SELECT * FROM categories`;
|
||||
db.all(selectCategoriesQuery, (err, rows) => {
|
||||
if (err) {
|
||||
console.error(err);
|
||||
res.status(500).json({ error: "Failed to fetch categories" });
|
||||
} else {
|
||||
res.json(rows);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Handle POST request to add a new category
|
||||
app.post("/addCategory", (req, res) => {
|
||||
const categoryName = req.body.categoryName;
|
||||
|
||||
// Insert the new category into the categories table
|
||||
const insertCategoryQuery = `INSERT INTO categories (name) VALUES (?)`;
|
||||
db.run(insertCategoryQuery, [categoryName], (err) => {
|
||||
if (err) {
|
||||
console.error(err);
|
||||
res.status(500).send("Error adding category");
|
||||
} else {
|
||||
res.send(`
|
||||
<script>
|
||||
alert('Category added successfully');
|
||||
window.location.href = '/';
|
||||
</script>
|
||||
`);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Handle POST request to add a new product
|
||||
app.post("/addProduct", (req, res) => {
|
||||
const productName = req.body.productName;
|
||||
const category = req.body.category;
|
||||
const price = req.body.price;
|
||||
const description = req.body.description;
|
||||
|
||||
let imageUrl = "";
|
||||
if (req.file) {
|
||||
imageUrl = req.file.filename;
|
||||
}
|
||||
|
||||
// Insert the new product into the products table
|
||||
const insertProductQuery = `INSERT INTO products (name, catid, price, description) VALUES (?, ?, ?, ?)`;
|
||||
db.run(
|
||||
insertProductQuery,
|
||||
[productName, category, price, description],
|
||||
(err) => {
|
||||
if (err) {
|
||||
console.error(err);
|
||||
res.status(500).send("Error adding product");
|
||||
} else {
|
||||
res.send(`
|
||||
<script>
|
||||
alert('Category added successfully');
|
||||
window.location.href = '/';
|
||||
</script>
|
||||
`);
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
// Start the server
|
||||
app.listen(3000, () => {
|
||||
console.log("Server started on port 3000");
|
||||
});
|
BIN
tsc1877/task1/_ref/paymentsequence_Simple.png
(Stored with Git LFS)
Normal file
BIN
tsc1877/task1/_ref/paymentsequence_Simple.png
(Stored with Git LFS)
Normal file
Binary file not shown.
5
tsc1877/task1/aws/workspace/.env.example
Normal file
5
tsc1877/task1/aws/workspace/.env.example
Normal file
@@ -0,0 +1,5 @@
|
||||
DB_HOST=localhost
|
||||
DB_PORT=6033
|
||||
DB_NAME=app_db
|
||||
DB_USER=db_user
|
||||
DB_PASSWORD=db_user_pass
|
12
tsc1877/task1/aws/workspace/README.md
Normal file
12
tsc1877/task1/aws/workspace/README.md
Normal file
@@ -0,0 +1,12 @@
|
||||
```batch
|
||||
|
||||
> .\dc_up.bat
|
||||
|
||||
```
|
||||
|
||||
*nix
|
||||
```batch
|
||||
|
||||
> .\dc_up.sh
|
||||
|
||||
```
|
@@ -0,0 +1,51 @@
|
||||
// ** MUI Imports
|
||||
import Box from '@mui/material/Box';
|
||||
import Card from '@mui/material/Card';
|
||||
import Avatar from '@mui/material/Avatar';
|
||||
import IconButton from '@mui/material/IconButton';
|
||||
import Typography from '@mui/material/Typography';
|
||||
import CardContent from '@mui/material/CardContent';
|
||||
|
||||
// ** Icons Imports
|
||||
import DotsVertical from 'mdi-material-ui/DotsVertical';
|
||||
|
||||
const CardStatsVertical = props => {
|
||||
// ** Props
|
||||
const { title, subtitle, color, icon, stats, trend, trendNumber } = props;
|
||||
|
||||
return (
|
||||
<Card>
|
||||
<CardContent>
|
||||
<Box sx={{ display: 'flex', marginBottom: 5.5, alignItems: 'flex-start', justifyContent: 'space-between' }}>
|
||||
<Avatar sx={{ boxShadow: 3, marginRight: 4, color: 'common.white', backgroundColor: `${color}.main` }}>
|
||||
{icon}
|
||||
</Avatar>
|
||||
<IconButton size="small" aria-label="settings" className="card-more-options" sx={{ color: 'text.secondary' }}>
|
||||
<DotsVertical />
|
||||
</IconButton>
|
||||
</Box>
|
||||
<Typography sx={{ fontWeight: 600, fontSize: '0.875rem' }}>{title}</Typography>
|
||||
<Box sx={{ marginTop: 1.5, display: 'flex', flexWrap: 'wrap', marginBottom: 1.5, alignItems: 'flex-start' }}>
|
||||
<Typography variant="h6" sx={{ mr: 2 }}>
|
||||
{stats}
|
||||
</Typography>
|
||||
<Typography
|
||||
component="sup"
|
||||
variant="caption"
|
||||
sx={{ color: trend === 'positive' ? 'success.main' : 'error.main' }}
|
||||
>
|
||||
{trendNumber}
|
||||
</Typography>
|
||||
</Box>
|
||||
<Typography variant="caption">{subtitle}</Typography>
|
||||
</CardContent>
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
|
||||
export default CardStatsVertical;
|
||||
|
||||
CardStatsVertical.defaultProps = {
|
||||
color: 'primary',
|
||||
trend: 'positive',
|
||||
};
|
7
tsc1877/task1/aws/workspace/admin/src/@core/components/react-apexcharts/index.js
vendored
Normal file
7
tsc1877/task1/aws/workspace/admin/src/@core/components/react-apexcharts/index.js
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
// ** Next Import
|
||||
import dynamic from 'next/dynamic';
|
||||
|
||||
// ! To avoid 'Window is not defined' error
|
||||
const ReactApexcharts = dynamic(() => import('react-apexcharts'), { ssr: false });
|
||||
|
||||
export default ReactApexcharts;
|
@@ -0,0 +1,39 @@
|
||||
// ** MUI Imports
|
||||
import Zoom from '@mui/material/Zoom';
|
||||
import { styled } from '@mui/material/styles';
|
||||
import useScrollTrigger from '@mui/material/useScrollTrigger';
|
||||
|
||||
const ScrollToTopStyled = styled('div')(({ theme }) => ({
|
||||
zIndex: 11,
|
||||
position: 'fixed',
|
||||
right: theme.spacing(6),
|
||||
bottom: theme.spacing(10),
|
||||
}));
|
||||
|
||||
const ScrollToTop = props => {
|
||||
// ** Props
|
||||
const { children, className } = props;
|
||||
|
||||
// ** init trigger
|
||||
const trigger = useScrollTrigger({
|
||||
threshold: 400,
|
||||
disableHysteresis: true,
|
||||
});
|
||||
|
||||
const handleClick = () => {
|
||||
const anchor = document.querySelector('body');
|
||||
if (anchor) {
|
||||
anchor.scrollIntoView({ behavior: 'smooth' });
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Zoom in={trigger}>
|
||||
<ScrollToTopStyled className={className} onClick={handleClick} role="presentation">
|
||||
{children}
|
||||
</ScrollToTopStyled>
|
||||
</Zoom>
|
||||
);
|
||||
};
|
||||
|
||||
export default ScrollToTop;
|
@@ -0,0 +1,30 @@
|
||||
// ** React Imports
|
||||
import { createContext, useState } from 'react';
|
||||
|
||||
// ** ThemeConfig Import
|
||||
import themeConfig from 'src/configs/themeConfig';
|
||||
|
||||
const initialSettings = {
|
||||
themeColor: 'primary',
|
||||
mode: themeConfig.mode,
|
||||
contentWidth: themeConfig.contentWidth,
|
||||
};
|
||||
|
||||
// ** Create Context
|
||||
export const SettingsContext = createContext({
|
||||
saveSettings: () => null,
|
||||
settings: initialSettings,
|
||||
});
|
||||
|
||||
export const SettingsProvider = ({ children }) => {
|
||||
// ** State
|
||||
const [settings, setSettings] = useState({ ...initialSettings });
|
||||
|
||||
const saveSettings = updatedSettings => {
|
||||
setSettings(updatedSettings);
|
||||
};
|
||||
|
||||
return <SettingsContext.Provider value={{ settings, saveSettings }}>{children}</SettingsContext.Provider>;
|
||||
};
|
||||
|
||||
export const SettingsConsumer = SettingsContext.Consumer;
|
@@ -0,0 +1,4 @@
|
||||
import { useContext } from 'react';
|
||||
import { SettingsContext } from 'src/@core/context/settingsContext';
|
||||
|
||||
export const useSettings = () => useContext(SettingsContext);
|
@@ -0,0 +1,37 @@
|
||||
// ** MUI Imports
|
||||
import { styled } from '@mui/material/styles';
|
||||
import Box from '@mui/material/Box';
|
||||
|
||||
// Styled component for Blank Layout component
|
||||
const BlankLayoutWrapper = styled(Box)(({ theme }) => ({
|
||||
height: '100vh',
|
||||
|
||||
// For V1 Blank layout pages
|
||||
'& .content-center': {
|
||||
display: 'flex',
|
||||
minHeight: '100vh',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
padding: theme.spacing(5),
|
||||
},
|
||||
|
||||
// For V2 Blank layout pages
|
||||
'& .content-right': {
|
||||
display: 'flex',
|
||||
minHeight: '100vh',
|
||||
overflowX: 'hidden',
|
||||
position: 'relative',
|
||||
},
|
||||
}));
|
||||
|
||||
const BlankLayout = ({ children }) => {
|
||||
return (
|
||||
<BlankLayoutWrapper className="layout-wrapper">
|
||||
<Box className="app-content" sx={{ minHeight: '100vh', overflowX: 'hidden', position: 'relative' }}>
|
||||
{children}
|
||||
</Box>
|
||||
</BlankLayoutWrapper>
|
||||
);
|
||||
};
|
||||
|
||||
export default BlankLayout;
|
@@ -0,0 +1,104 @@
|
||||
// ** MUI Imports
|
||||
import { styled } from '@mui/material/styles';
|
||||
import Box from '@mui/material/Box';
|
||||
import { Badge, Button, IconButton, Stack, Typography } from '@mui/material';
|
||||
import { useRouter } from 'next/router';
|
||||
import HomeIcon from '@mui/icons-material/Home';
|
||||
import { CartConsumer, CartContext, CartProvider } from 'src/contexts/cart';
|
||||
import { useContext, useEffect, useState } from 'react';
|
||||
import CartIcon from './components/CartIcon';
|
||||
import AccountBoxIcon from '@mui/icons-material/AccountBox';
|
||||
import CheckSession from 'src/api/checkSession';
|
||||
import { AuthContext, AuthProvider } from 'src/contexts/auth';
|
||||
|
||||
// Styled component for Blank Layout component
|
||||
const ShopfrontLayoutWrapper = styled(Box)(({ theme }) => ({
|
||||
height: '100vh',
|
||||
|
||||
// For V1 Blank layout pages
|
||||
'& .content-center': {
|
||||
display: 'flex',
|
||||
minHeight: '100vh',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
padding: theme.spacing(5),
|
||||
},
|
||||
|
||||
// For V2 Blank layout pages
|
||||
'& .content-right': {
|
||||
display: 'flex',
|
||||
minHeight: '100vh',
|
||||
overflowX: 'hidden',
|
||||
position: 'relative',
|
||||
},
|
||||
}));
|
||||
|
||||
const ShopfrontLayout = ({ children }) => {
|
||||
const router = useRouter();
|
||||
const [data, setData] = useState({});
|
||||
const { username, setUsername } = useContext(AuthContext);
|
||||
|
||||
useEffect(() => {
|
||||
const check = async () => {
|
||||
try {
|
||||
let { session } = JSON.parse(localStorage.getItem('session')) || '';
|
||||
|
||||
let data = await CheckSession({ session });
|
||||
if (data['status'] != 'OK') {
|
||||
return route.replace('/shopfront/login');
|
||||
} else {
|
||||
setData(data);
|
||||
setUsername(data['username']);
|
||||
}
|
||||
} catch (error) {}
|
||||
};
|
||||
|
||||
return check();
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<CartProvider>
|
||||
<ShopfrontLayoutWrapper className="layout-wrapper">
|
||||
<Box className="app-content" sx={{ minHeight: '100vh', overflowX: 'hidden', position: 'relative' }}>
|
||||
<Stack direction="column" alignItems={'center'} justifyContent={'center'}>
|
||||
<Box sx={{ width: '80vw' }}>
|
||||
<Stack direction="column">
|
||||
<Stack direction="row" justifyContent={'space-between'} alignItems={'center'} minHeight={'10vh'}>
|
||||
<Box style={{ width: 'calc ( 80vw / 3 )' }}>
|
||||
<Typography variant="h5">Hi, {username || 'Guest'}</Typography>
|
||||
</Box>
|
||||
<Box style={{ width: 'calc ( 80vw / 3 )' }}>
|
||||
<Typography variant="h5">VTKH Mall</Typography>
|
||||
</Box>
|
||||
|
||||
<Box style={{ width: 'calc ( 80vw / 3 )' }}>
|
||||
<IconButton
|
||||
onClick={() => {
|
||||
router.push('/shopfront/customer/profile');
|
||||
}}
|
||||
>
|
||||
<AccountBoxIcon />
|
||||
</IconButton>
|
||||
<IconButton
|
||||
onClick={() => {
|
||||
router.push('/shopfront');
|
||||
}}
|
||||
>
|
||||
<HomeIcon />
|
||||
</IconButton>
|
||||
|
||||
<CartIcon />
|
||||
</Box>
|
||||
</Stack>
|
||||
{children}
|
||||
<Box height={'5rem'}></Box>
|
||||
</Stack>
|
||||
</Box>
|
||||
</Stack>
|
||||
</Box>
|
||||
</ShopfrontLayoutWrapper>
|
||||
</CartProvider>
|
||||
);
|
||||
};
|
||||
|
||||
export default ShopfrontLayout;
|
@@ -0,0 +1,109 @@
|
||||
// ** React Imports
|
||||
import { useState } from 'react';
|
||||
|
||||
// ** MUI Imports
|
||||
import Fab from '@mui/material/Fab';
|
||||
import { styled } from '@mui/material/styles';
|
||||
import Box from '@mui/material/Box';
|
||||
|
||||
// ** Icons Imports
|
||||
import ArrowUp from 'mdi-material-ui/ArrowUp';
|
||||
|
||||
// ** Theme Config Import
|
||||
import themeConfig from 'src/configs/themeConfig';
|
||||
|
||||
// ** Components
|
||||
import AppBar from './components/vertical/appBar';
|
||||
import Navigation from './components/vertical/navigation';
|
||||
import Footer from './components/shared-components/footer';
|
||||
import ScrollToTop from 'src/@core/components/scroll-to-top';
|
||||
|
||||
// ** Styled Component
|
||||
import DatePickerWrapper from 'src/@core/styles/libs/react-datepicker';
|
||||
|
||||
const VerticalLayoutWrapper = styled('div')({
|
||||
height: '100%',
|
||||
display: 'flex',
|
||||
});
|
||||
|
||||
const MainContentWrapper = styled(Box)({
|
||||
flexGrow: 1,
|
||||
minWidth: 0,
|
||||
display: 'flex',
|
||||
minHeight: '100vh',
|
||||
flexDirection: 'column',
|
||||
});
|
||||
|
||||
const ContentWrapper = styled('main')(({ theme }) => ({
|
||||
flexGrow: 1,
|
||||
width: '100%',
|
||||
padding: theme.spacing(6),
|
||||
transition: 'padding .25s ease-in-out',
|
||||
[theme.breakpoints.down('sm')]: {
|
||||
paddingLeft: theme.spacing(4),
|
||||
paddingRight: theme.spacing(4),
|
||||
},
|
||||
}));
|
||||
|
||||
const VerticalLayout = props => {
|
||||
// ** Props
|
||||
const { settings, children, scrollToTop } = props;
|
||||
|
||||
// ** Vars
|
||||
const { contentWidth } = settings;
|
||||
const navWidth = themeConfig.navigationSize;
|
||||
|
||||
// ** States
|
||||
const [navVisible, setNavVisible] = useState(false);
|
||||
|
||||
// ** Toggle Functions
|
||||
const toggleNavVisibility = () => setNavVisible(!navVisible);
|
||||
|
||||
return (
|
||||
<>
|
||||
<VerticalLayoutWrapper className="layout-wrapper">
|
||||
<Navigation
|
||||
navWidth={navWidth}
|
||||
navVisible={navVisible}
|
||||
setNavVisible={setNavVisible}
|
||||
toggleNavVisibility={toggleNavVisibility}
|
||||
{...props}
|
||||
/>
|
||||
<MainContentWrapper className="layout-content-wrapper">
|
||||
<AppBar toggleNavVisibility={toggleNavVisibility} {...props} />
|
||||
|
||||
<ContentWrapper
|
||||
className="layout-page-content"
|
||||
sx={{
|
||||
...(contentWidth === 'boxed' && {
|
||||
mx: 'auto',
|
||||
'@media (min-width:1440px)': { maxWidth: 1440 },
|
||||
'@media (min-width:1200px)': { maxWidth: '100%' },
|
||||
}),
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</ContentWrapper>
|
||||
|
||||
<Footer {...props} />
|
||||
|
||||
<DatePickerWrapper sx={{ zIndex: 11 }}>
|
||||
<Box id="react-datepicker-portal"></Box>
|
||||
</DatePickerWrapper>
|
||||
</MainContentWrapper>
|
||||
</VerticalLayoutWrapper>
|
||||
|
||||
{scrollToTop ? (
|
||||
scrollToTop(props)
|
||||
) : (
|
||||
<ScrollToTop className="mui-fixed">
|
||||
<Fab color="primary" size="small" aria-label="scroll back to top">
|
||||
<ArrowUp />
|
||||
</Fab>
|
||||
</ScrollToTop>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default VerticalLayout;
|
@@ -0,0 +1,29 @@
|
||||
import ShoppingCartIcon from '@mui/icons-material/ShoppingCart';
|
||||
|
||||
import { Badge, IconButton } from '@mui/material';
|
||||
import { useRouter } from 'next/router';
|
||||
import { useContext } from 'react';
|
||||
import { CartContext } from 'src/contexts/cart';
|
||||
|
||||
function CartIcon() {
|
||||
let router = useRouter();
|
||||
let { cart } = useContext(CartContext);
|
||||
|
||||
if (!cart) return <></>;
|
||||
|
||||
return (
|
||||
<>
|
||||
<IconButton
|
||||
onClick={() => {
|
||||
router.push('/shopfront/cart');
|
||||
}}
|
||||
>
|
||||
<Badge badgeContent={cart?.length} color="primary">
|
||||
<ShoppingCartIcon />
|
||||
</Badge>
|
||||
</IconButton>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export default CartIcon;
|
@@ -0,0 +1,30 @@
|
||||
import IconButton from '@mui/material/IconButton';
|
||||
|
||||
// ** Icons Imports
|
||||
import WeatherNight from 'mdi-material-ui/WeatherNight';
|
||||
import WeatherSunny from 'mdi-material-ui/WeatherSunny';
|
||||
|
||||
const ModeToggler = props => {
|
||||
// ** Props
|
||||
const { settings, saveSettings } = props;
|
||||
|
||||
const handleModeChange = mode => {
|
||||
saveSettings({ ...settings, mode });
|
||||
};
|
||||
|
||||
const handleModeToggle = () => {
|
||||
if (settings.mode === 'light') {
|
||||
handleModeChange('dark');
|
||||
} else {
|
||||
handleModeChange('light');
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<IconButton color="inherit" aria-haspopup="true" onClick={handleModeToggle}>
|
||||
{settings.mode === 'dark' ? <WeatherSunny /> : <WeatherNight />}
|
||||
</IconButton>
|
||||
);
|
||||
};
|
||||
|
||||
export default ModeToggler;
|
@@ -0,0 +1,217 @@
|
||||
// ** React Imports
|
||||
import { useState, Fragment } from 'react';
|
||||
|
||||
// ** MUI Imports
|
||||
import Box from '@mui/material/Box';
|
||||
import Chip from '@mui/material/Chip';
|
||||
import Button from '@mui/material/Button';
|
||||
import IconButton from '@mui/material/IconButton';
|
||||
import { styled } from '@mui/material/styles';
|
||||
import useMediaQuery from '@mui/material/useMediaQuery';
|
||||
import MuiMenu from '@mui/material/Menu';
|
||||
import MuiAvatar from '@mui/material/Avatar';
|
||||
import MuiMenuItem from '@mui/material/MenuItem';
|
||||
import Typography from '@mui/material/Typography';
|
||||
|
||||
// ** Icons Imports
|
||||
import BellOutline from 'mdi-material-ui/BellOutline';
|
||||
|
||||
// ** Third Party Components
|
||||
import PerfectScrollbarComponent from 'react-perfect-scrollbar';
|
||||
|
||||
// ** Styled Menu component
|
||||
const Menu = styled(MuiMenu)(({ theme }) => ({
|
||||
'& .MuiMenu-paper': {
|
||||
width: 380,
|
||||
overflow: 'hidden',
|
||||
marginTop: theme.spacing(4),
|
||||
[theme.breakpoints.down('sm')]: {
|
||||
width: '100%',
|
||||
},
|
||||
},
|
||||
'& .MuiMenu-list': {
|
||||
padding: 0,
|
||||
},
|
||||
}));
|
||||
|
||||
// ** Styled MenuItem component
|
||||
const MenuItem = styled(MuiMenuItem)(({ theme }) => ({
|
||||
paddingTop: theme.spacing(3),
|
||||
paddingBottom: theme.spacing(3),
|
||||
borderBottom: `1px solid ${theme.palette.divider}`,
|
||||
}));
|
||||
|
||||
const styles = {
|
||||
maxHeight: 349,
|
||||
'& .MuiMenuItem-root:last-of-type': {
|
||||
border: 0,
|
||||
},
|
||||
};
|
||||
|
||||
// ** Styled PerfectScrollbar component
|
||||
const PerfectScrollbar = styled(PerfectScrollbarComponent)({
|
||||
...styles,
|
||||
});
|
||||
|
||||
// ** Styled Avatar component
|
||||
const Avatar = styled(MuiAvatar)({
|
||||
width: '2.375rem',
|
||||
height: '2.375rem',
|
||||
fontSize: '1.125rem',
|
||||
});
|
||||
|
||||
// ** Styled component for the title in MenuItems
|
||||
const MenuItemTitle = styled(Typography)(({ theme }) => ({
|
||||
fontWeight: 600,
|
||||
flex: '1 1 100%',
|
||||
overflow: 'hidden',
|
||||
fontSize: '0.875rem',
|
||||
whiteSpace: 'nowrap',
|
||||
textOverflow: 'ellipsis',
|
||||
marginBottom: theme.spacing(0.75),
|
||||
}));
|
||||
|
||||
// ** Styled component for the subtitle in MenuItems
|
||||
const MenuItemSubtitle = styled(Typography)({
|
||||
flex: '1 1 100%',
|
||||
overflow: 'hidden',
|
||||
whiteSpace: 'nowrap',
|
||||
textOverflow: 'ellipsis',
|
||||
});
|
||||
|
||||
const NotificationDropdown = () => {
|
||||
// ** States
|
||||
const [anchorEl, setAnchorEl] = useState(null);
|
||||
|
||||
// ** Hook
|
||||
const hidden = useMediaQuery(theme => theme.breakpoints.down('lg'));
|
||||
|
||||
const handleDropdownOpen = event => {
|
||||
setAnchorEl(event.currentTarget);
|
||||
};
|
||||
|
||||
const handleDropdownClose = () => {
|
||||
setAnchorEl(null);
|
||||
};
|
||||
|
||||
const ScrollWrapper = ({ children }) => {
|
||||
if (hidden) {
|
||||
return <Box sx={{ ...styles, overflowY: 'auto', overflowX: 'hidden' }}>{children}</Box>;
|
||||
} else {
|
||||
return (
|
||||
<PerfectScrollbar options={{ wheelPropagation: false, suppressScrollX: true }}>{children}</PerfectScrollbar>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<IconButton color="inherit" aria-haspopup="true" onClick={handleDropdownOpen} aria-controls="customized-menu">
|
||||
<BellOutline />
|
||||
</IconButton>
|
||||
<Menu
|
||||
anchorEl={anchorEl}
|
||||
open={Boolean(anchorEl)}
|
||||
onClose={handleDropdownClose}
|
||||
anchorOrigin={{ vertical: 'bottom', horizontal: 'right' }}
|
||||
transformOrigin={{ vertical: 'top', horizontal: 'right' }}
|
||||
>
|
||||
<MenuItem disableRipple>
|
||||
<Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', width: '100%' }}>
|
||||
<Typography sx={{ fontWeight: 600 }}>Notifications</Typography>
|
||||
<Chip
|
||||
size="small"
|
||||
label="8 New"
|
||||
color="primary"
|
||||
sx={{ height: 20, fontSize: '0.75rem', fontWeight: 500, borderRadius: '10px' }}
|
||||
/>
|
||||
</Box>
|
||||
</MenuItem>
|
||||
<ScrollWrapper>
|
||||
<MenuItem onClick={handleDropdownClose}>
|
||||
<Box sx={{ width: '100%', display: 'flex', alignItems: 'center' }}>
|
||||
<Avatar alt="Flora" src="/images/avatars/4.png" />
|
||||
<Box sx={{ mx: 4, flex: '1 1', display: 'flex', overflow: 'hidden', flexDirection: 'column' }}>
|
||||
<MenuItemTitle>Congratulation Flora! 🎉</MenuItemTitle>
|
||||
<MenuItemSubtitle variant="body2">Won the monthly best seller badge</MenuItemSubtitle>
|
||||
</Box>
|
||||
<Typography variant="caption" sx={{ color: 'text.disabled' }}>
|
||||
Today
|
||||
</Typography>
|
||||
</Box>
|
||||
</MenuItem>
|
||||
<MenuItem onClick={handleDropdownClose}>
|
||||
<Box sx={{ width: '100%', display: 'flex', alignItems: 'center' }}>
|
||||
<Avatar sx={{ color: 'common.white', backgroundColor: 'primary.main' }}>VU</Avatar>
|
||||
<Box sx={{ mx: 4, flex: '1 1', display: 'flex', overflow: 'hidden', flexDirection: 'column' }}>
|
||||
<MenuItemTitle>New user registered.</MenuItemTitle>
|
||||
<MenuItemSubtitle variant="body2">5 hours ago</MenuItemSubtitle>
|
||||
</Box>
|
||||
<Typography variant="caption" sx={{ color: 'text.disabled' }}>
|
||||
Yesterday
|
||||
</Typography>
|
||||
</Box>
|
||||
</MenuItem>
|
||||
<MenuItem onClick={handleDropdownClose}>
|
||||
<Box sx={{ width: '100%', display: 'flex', alignItems: 'center' }}>
|
||||
<Avatar alt="message" src="/images/avatars/5.png" />
|
||||
<Box sx={{ mx: 4, flex: '1 1', display: 'flex', overflow: 'hidden', flexDirection: 'column' }}>
|
||||
<MenuItemTitle>New message received 👋🏻</MenuItemTitle>
|
||||
<MenuItemSubtitle variant="body2">You have 10 unread messages</MenuItemSubtitle>
|
||||
</Box>
|
||||
<Typography variant="caption" sx={{ color: 'text.disabled' }}>
|
||||
11 Aug
|
||||
</Typography>
|
||||
</Box>
|
||||
</MenuItem>
|
||||
<MenuItem onClick={handleDropdownClose}>
|
||||
<Box sx={{ width: '100%', display: 'flex', alignItems: 'center' }}>
|
||||
<img width={38} height={38} alt="paypal" src="/images/misc/paypal.png" />
|
||||
<Box sx={{ mx: 4, flex: '1 1', display: 'flex', overflow: 'hidden', flexDirection: 'column' }}>
|
||||
<MenuItemTitle>Paypal</MenuItemTitle>
|
||||
<MenuItemSubtitle variant="body2">Received Payment</MenuItemSubtitle>
|
||||
</Box>
|
||||
<Typography variant="caption" sx={{ color: 'text.disabled' }}>
|
||||
25 May
|
||||
</Typography>
|
||||
</Box>
|
||||
</MenuItem>
|
||||
<MenuItem onClick={handleDropdownClose}>
|
||||
<Box sx={{ width: '100%', display: 'flex', alignItems: 'center' }}>
|
||||
<Avatar alt="order" src="/images/avatars/3.png" />
|
||||
<Box sx={{ mx: 4, flex: '1 1', display: 'flex', overflow: 'hidden', flexDirection: 'column' }}>
|
||||
<MenuItemTitle>Revised Order 📦</MenuItemTitle>
|
||||
<MenuItemSubtitle variant="body2">New order revised from john</MenuItemSubtitle>
|
||||
</Box>
|
||||
<Typography variant="caption" sx={{ color: 'text.disabled' }}>
|
||||
19 Mar
|
||||
</Typography>
|
||||
</Box>
|
||||
</MenuItem>
|
||||
<MenuItem onClick={handleDropdownClose}>
|
||||
<Box sx={{ width: '100%', display: 'flex', alignItems: 'center' }}>
|
||||
<img width={38} height={38} alt="chart" src="/images/misc/chart.png" />
|
||||
<Box sx={{ mx: 4, flex: '1 1', display: 'flex', overflow: 'hidden', flexDirection: 'column' }}>
|
||||
<MenuItemTitle>Finance report has been generated</MenuItemTitle>
|
||||
<MenuItemSubtitle variant="body2">25 hrs ago</MenuItemSubtitle>
|
||||
</Box>
|
||||
<Typography variant="caption" sx={{ color: 'text.disabled' }}>
|
||||
27 Dec
|
||||
</Typography>
|
||||
</Box>
|
||||
</MenuItem>
|
||||
</ScrollWrapper>
|
||||
<MenuItem
|
||||
disableRipple
|
||||
sx={{ py: 3.5, borderBottom: 0, borderTop: theme => `1px solid ${theme.palette.divider}` }}
|
||||
>
|
||||
<Button fullWidth variant="contained" onClick={handleDropdownClose}>
|
||||
Read All Notifications
|
||||
</Button>
|
||||
</MenuItem>
|
||||
</Menu>
|
||||
</Fragment>
|
||||
);
|
||||
};
|
||||
|
||||
export default NotificationDropdown;
|
@@ -0,0 +1,143 @@
|
||||
// ** React Imports
|
||||
import { useState, Fragment } from 'react';
|
||||
|
||||
// ** Next Import
|
||||
import { useRouter } from 'next/router';
|
||||
|
||||
// ** MUI Imports
|
||||
import Box from '@mui/material/Box';
|
||||
import Menu from '@mui/material/Menu';
|
||||
import Badge from '@mui/material/Badge';
|
||||
import Avatar from '@mui/material/Avatar';
|
||||
import Divider from '@mui/material/Divider';
|
||||
import MenuItem from '@mui/material/MenuItem';
|
||||
import { styled } from '@mui/material/styles';
|
||||
import Typography from '@mui/material/Typography';
|
||||
|
||||
// ** Icons Imports
|
||||
import CogOutline from 'mdi-material-ui/CogOutline';
|
||||
import CurrencyUsd from 'mdi-material-ui/CurrencyUsd';
|
||||
import EmailOutline from 'mdi-material-ui/EmailOutline';
|
||||
import LogoutVariant from 'mdi-material-ui/LogoutVariant';
|
||||
import AccountOutline from 'mdi-material-ui/AccountOutline';
|
||||
import MessageOutline from 'mdi-material-ui/MessageOutline';
|
||||
import HelpCircleOutline from 'mdi-material-ui/HelpCircleOutline';
|
||||
|
||||
// ** Styled Components
|
||||
const BadgeContentSpan = styled('span')(({ theme }) => ({
|
||||
width: 8,
|
||||
height: 8,
|
||||
borderRadius: '50%',
|
||||
backgroundColor: theme.palette.success.main,
|
||||
boxShadow: `0 0 0 2px ${theme.palette.background.paper}`,
|
||||
}));
|
||||
|
||||
const UserDropdown = () => {
|
||||
// ** States
|
||||
const [anchorEl, setAnchorEl] = useState(null);
|
||||
|
||||
// ** Hooks
|
||||
const router = useRouter();
|
||||
|
||||
const handleDropdownOpen = event => {
|
||||
setAnchorEl(event.currentTarget);
|
||||
};
|
||||
|
||||
const handleDropdownClose = url => {
|
||||
if (url) {
|
||||
router.push(url);
|
||||
}
|
||||
setAnchorEl(null);
|
||||
};
|
||||
|
||||
const styles = {
|
||||
py: 2,
|
||||
px: 4,
|
||||
width: '100%',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
color: 'text.primary',
|
||||
textDecoration: 'none',
|
||||
'& svg': {
|
||||
fontSize: '1.375rem',
|
||||
color: 'text.secondary',
|
||||
},
|
||||
};
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<Badge>Hello user,</Badge>
|
||||
<Menu
|
||||
anchorEl={anchorEl}
|
||||
open={Boolean(anchorEl)}
|
||||
onClose={() => handleDropdownClose()}
|
||||
sx={{ '& .MuiMenu-paper': { width: 230, marginTop: 4 } }}
|
||||
anchorOrigin={{ vertical: 'bottom', horizontal: 'right' }}
|
||||
transformOrigin={{ vertical: 'top', horizontal: 'right' }}
|
||||
>
|
||||
<Box sx={{ pt: 2, pb: 3, px: 4 }}>
|
||||
<Box sx={{ display: 'flex', alignItems: 'center' }}>
|
||||
<Badge
|
||||
overlap="circular"
|
||||
badgeContent={<BadgeContentSpan />}
|
||||
anchorOrigin={{ vertical: 'bottom', horizontal: 'right' }}
|
||||
>
|
||||
<Avatar alt="John Doe" src="/images/avatars/1.png" sx={{ width: '2.5rem', height: '2.5rem' }} />
|
||||
</Badge>
|
||||
<Box sx={{ display: 'flex', marginLeft: 3, alignItems: 'flex-start', flexDirection: 'column' }}>
|
||||
<Typography sx={{ fontWeight: 600 }}>John Doe</Typography>
|
||||
<Typography variant="body2" sx={{ fontSize: '0.8rem', color: 'text.disabled' }}>
|
||||
Admin
|
||||
</Typography>
|
||||
</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
<Divider sx={{ mt: 0, mb: 1 }} />
|
||||
<MenuItem sx={{ p: 0 }} onClick={() => handleDropdownClose()}>
|
||||
<Box sx={styles}>
|
||||
<AccountOutline sx={{ marginRight: 2 }} />
|
||||
Profile
|
||||
</Box>
|
||||
</MenuItem>
|
||||
<MenuItem sx={{ p: 0 }} onClick={() => handleDropdownClose()}>
|
||||
<Box sx={styles}>
|
||||
<EmailOutline sx={{ marginRight: 2 }} />
|
||||
Inbox
|
||||
</Box>
|
||||
</MenuItem>
|
||||
<MenuItem sx={{ p: 0 }} onClick={() => handleDropdownClose()}>
|
||||
<Box sx={styles}>
|
||||
<MessageOutline sx={{ marginRight: 2 }} />
|
||||
Chat
|
||||
</Box>
|
||||
</MenuItem>
|
||||
<Divider />
|
||||
<MenuItem sx={{ p: 0 }} onClick={() => handleDropdownClose()}>
|
||||
<Box sx={styles}>
|
||||
<CogOutline sx={{ marginRight: 2 }} />
|
||||
Settings
|
||||
</Box>
|
||||
</MenuItem>
|
||||
<MenuItem sx={{ p: 0 }} onClick={() => handleDropdownClose()}>
|
||||
<Box sx={styles}>
|
||||
<CurrencyUsd sx={{ marginRight: 2 }} />
|
||||
Pricing
|
||||
</Box>
|
||||
</MenuItem>
|
||||
<MenuItem sx={{ p: 0 }} onClick={() => handleDropdownClose()}>
|
||||
<Box sx={styles}>
|
||||
<HelpCircleOutline sx={{ marginRight: 2 }} />
|
||||
FAQ
|
||||
</Box>
|
||||
</MenuItem>
|
||||
<Divider />
|
||||
<MenuItem sx={{ py: 2 }} onClick={() => handleDropdownClose('/pages/login')}>
|
||||
<LogoutVariant sx={{ marginRight: 2, fontSize: '1.375rem', color: 'text.secondary' }} />
|
||||
Logout
|
||||
</MenuItem>
|
||||
</Menu>
|
||||
</Fragment>
|
||||
);
|
||||
};
|
||||
|
||||
export default UserDropdown;
|
@@ -0,0 +1,53 @@
|
||||
// ** MUI Imports
|
||||
import Box from '@mui/material/Box';
|
||||
import Link from '@mui/material/Link';
|
||||
import Typography from '@mui/material/Typography';
|
||||
import useMediaQuery from '@mui/material/useMediaQuery';
|
||||
|
||||
const FooterContent = () => {
|
||||
// ** Var
|
||||
const hidden = useMediaQuery(theme => theme.breakpoints.down('md'));
|
||||
|
||||
return (
|
||||
<Box sx={{ display: 'flex', flexWrap: 'wrap', alignItems: 'center', justifyContent: 'space-between' }}>
|
||||
<Typography sx={{ mr: 2 }}>
|
||||
{`© ${new Date().getFullYear()}, Made with `}
|
||||
<Box component="span" sx={{ color: 'error.main' }}>
|
||||
❤️
|
||||
</Box>
|
||||
{` by `}
|
||||
<Link target="_blank" href="https://themeselection.com/">
|
||||
ThemeSelection
|
||||
</Link>{' '}
|
||||
and for project
|
||||
</Typography>
|
||||
{hidden ? null : (
|
||||
<Box sx={{ display: 'flex', flexWrap: 'wrap', alignItems: 'center', '& :not(:last-child)': { mr: 4 } }}>
|
||||
<Link
|
||||
target="_blank"
|
||||
href="https://github.com/themeselection/materio-mui-react-nextjs-admin-template-free/blob/main/LICENSE"
|
||||
>
|
||||
MIT License
|
||||
</Link>
|
||||
<Link target="_blank" href="https://themeselection.com/">
|
||||
More Themes
|
||||
</Link>
|
||||
<Link
|
||||
target="_blank"
|
||||
href="https://github.com/themeselection/materio-mui-react-nextjs-admin-template-free/blob/main/README.md"
|
||||
>
|
||||
Documentation
|
||||
</Link>
|
||||
<Link
|
||||
target="_blank"
|
||||
href="https://github.com/themeselection/materio-mui-react-nextjs-admin-template-free/issues"
|
||||
>
|
||||
Support
|
||||
</Link>
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
export default FooterContent;
|
@@ -0,0 +1,45 @@
|
||||
// ** MUI Imports
|
||||
import Box from '@mui/material/Box';
|
||||
import { useTheme } from '@mui/material/styles';
|
||||
|
||||
// ** Footer Content Component
|
||||
import FooterContent from './FooterContent';
|
||||
|
||||
const Footer = props => {
|
||||
// ** Props
|
||||
const { settings, footerContent: userFooterContent } = props;
|
||||
|
||||
// ** Hook
|
||||
const theme = useTheme();
|
||||
|
||||
// ** Vars
|
||||
const { contentWidth } = settings;
|
||||
|
||||
return (
|
||||
<Box
|
||||
component="footer"
|
||||
className="layout-footer"
|
||||
sx={{
|
||||
zIndex: 10,
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
className="footer-content-container"
|
||||
sx={{
|
||||
width: '100%',
|
||||
borderTopLeftRadius: 14,
|
||||
borderTopRightRadius: 14,
|
||||
padding: theme.spacing(4, 6),
|
||||
...(contentWidth === 'boxed' && { '@media (min-width:1440px)': { maxWidth: 1440 } }),
|
||||
}}
|
||||
>
|
||||
{userFooterContent ? userFooterContent(props) : <FooterContent />}
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
export default Footer;
|
@@ -0,0 +1,56 @@
|
||||
// ** MUI Imports
|
||||
import { styled, useTheme } from '@mui/material/styles';
|
||||
import MuiAppBar from '@mui/material/AppBar';
|
||||
import MuiToolbar from '@mui/material/Toolbar';
|
||||
|
||||
const AppBar = styled(MuiAppBar)(({ theme }) => ({
|
||||
transition: 'none',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
padding: theme.spacing(0, 6),
|
||||
backgroundColor: 'transparent',
|
||||
color: theme.palette.text.primary,
|
||||
minHeight: theme.mixins.toolbar.minHeight,
|
||||
[theme.breakpoints.down('sm')]: {
|
||||
paddingLeft: theme.spacing(4),
|
||||
paddingRight: theme.spacing(4),
|
||||
},
|
||||
}));
|
||||
|
||||
const Toolbar = styled(MuiToolbar)(({ theme }) => ({
|
||||
width: '100%',
|
||||
borderBottomLeftRadius: 10,
|
||||
borderBottomRightRadius: 10,
|
||||
padding: `${theme.spacing(0)} !important`,
|
||||
minHeight: `${theme.mixins.toolbar.minHeight}px !important`,
|
||||
transition:
|
||||
'padding .25s ease-in-out, box-shadow .25s ease-in-out, backdrop-filter .25s ease-in-out, background-color .25s ease-in-out',
|
||||
}));
|
||||
|
||||
const LayoutAppBar = props => {
|
||||
// ** Props
|
||||
const { settings, verticalAppBarContent: userVerticalAppBarContent } = props;
|
||||
|
||||
// ** Hooks
|
||||
const theme = useTheme();
|
||||
|
||||
// ** Vars
|
||||
const { contentWidth } = settings;
|
||||
|
||||
return (
|
||||
<AppBar elevation={0} color="default" className="layout-navbar" position="static">
|
||||
<Toolbar
|
||||
className="navbar-content-container"
|
||||
sx={{
|
||||
...(contentWidth === 'boxed' && {
|
||||
'@media (min-width:1440px)': { maxWidth: `calc(1440px - ${theme.spacing(6)} * 2)` },
|
||||
}),
|
||||
}}
|
||||
>
|
||||
{(userVerticalAppBarContent && userVerticalAppBarContent(props)) || null}
|
||||
</Toolbar>
|
||||
</AppBar>
|
||||
);
|
||||
};
|
||||
|
||||
export default LayoutAppBar;
|
@@ -0,0 +1,66 @@
|
||||
// ** MUI Imports
|
||||
import { styled, useTheme } from '@mui/material/styles';
|
||||
import MuiSwipeableDrawer from '@mui/material/SwipeableDrawer';
|
||||
|
||||
const SwipeableDrawer = styled(MuiSwipeableDrawer)({
|
||||
overflowX: 'hidden',
|
||||
transition: 'width .25s ease-in-out',
|
||||
'& ul': {
|
||||
listStyle: 'none',
|
||||
},
|
||||
'& .MuiListItem-gutters': {
|
||||
paddingLeft: 4,
|
||||
paddingRight: 4,
|
||||
},
|
||||
'& .MuiDrawer-paper': {
|
||||
left: 'unset',
|
||||
right: 'unset',
|
||||
overflowX: 'hidden',
|
||||
transition: 'width .25s ease-in-out, box-shadow .25s ease-in-out',
|
||||
},
|
||||
});
|
||||
|
||||
const Drawer = props => {
|
||||
// ** Props
|
||||
const { hidden, children, navWidth, navVisible, setNavVisible } = props;
|
||||
|
||||
// ** Hook
|
||||
const theme = useTheme();
|
||||
|
||||
// Drawer Props for Mobile & Tablet screens
|
||||
const MobileDrawerProps = {
|
||||
open: navVisible,
|
||||
onOpen: () => setNavVisible(true),
|
||||
onClose: () => setNavVisible(false),
|
||||
ModalProps: {
|
||||
keepMounted: true, // Better open performance on mobile.
|
||||
},
|
||||
};
|
||||
|
||||
// Drawer Props for Desktop screens
|
||||
const DesktopDrawerProps = {
|
||||
open: true,
|
||||
onOpen: () => null,
|
||||
onClose: () => null,
|
||||
};
|
||||
|
||||
return (
|
||||
<SwipeableDrawer
|
||||
className="layout-vertical-nav"
|
||||
variant={hidden ? 'temporary' : 'permanent'}
|
||||
{...(hidden ? { ...MobileDrawerProps } : { ...DesktopDrawerProps })}
|
||||
PaperProps={{ sx: { width: navWidth } }}
|
||||
sx={{
|
||||
width: navWidth,
|
||||
'& .MuiDrawer-paper': {
|
||||
borderRight: 0,
|
||||
backgroundColor: theme.palette.background.default,
|
||||
},
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</SwipeableDrawer>
|
||||
);
|
||||
};
|
||||
|
||||
export default Drawer;
|
@@ -0,0 +1,119 @@
|
||||
// ** Next Import
|
||||
import Link from 'next/link';
|
||||
|
||||
// ** MUI Imports
|
||||
import Box from '@mui/material/Box';
|
||||
import { styled, useTheme } from '@mui/material/styles';
|
||||
import Typography from '@mui/material/Typography';
|
||||
|
||||
// ** Configs
|
||||
import themeConfig from 'src/configs/themeConfig';
|
||||
|
||||
// ** Styled Components
|
||||
const MenuHeaderWrapper = styled(Box)(({ theme }) => ({
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
paddingRight: theme.spacing(4.5),
|
||||
transition: 'padding .25s ease-in-out',
|
||||
minHeight: theme.mixins.toolbar.minHeight,
|
||||
}));
|
||||
|
||||
const HeaderTitle = styled(Typography)(({ theme }) => ({
|
||||
fontWeight: 600,
|
||||
lineHeight: 'normal',
|
||||
textTransform: 'uppercase',
|
||||
color: theme.palette.text.primary,
|
||||
transition: 'opacity .25s ease-in-out, margin .25s ease-in-out',
|
||||
}));
|
||||
|
||||
const StyledLink = styled('a')({
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
textDecoration: 'none',
|
||||
});
|
||||
|
||||
const VerticalNavHeader = props => {
|
||||
// ** Props
|
||||
const { verticalNavMenuBranding: userVerticalNavMenuBranding } = props;
|
||||
|
||||
// ** Hooks
|
||||
const theme = useTheme();
|
||||
|
||||
return (
|
||||
<MenuHeaderWrapper className="nav-header" sx={{ pl: 6 }}>
|
||||
{userVerticalNavMenuBranding ? (
|
||||
userVerticalNavMenuBranding(props)
|
||||
) : (
|
||||
<Link href="/" passHref>
|
||||
<StyledLink>
|
||||
<svg
|
||||
width={30}
|
||||
height={25}
|
||||
version="1.1"
|
||||
viewBox="0 0 30 23"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlnsXlink="http://www.w3.org/1999/xlink"
|
||||
>
|
||||
<g stroke="none" strokeWidth="1" fill="none" fillRule="evenodd">
|
||||
<g id="Artboard" transform="translate(-95.000000, -51.000000)">
|
||||
<g id="logo" transform="translate(95.000000, 50.000000)">
|
||||
<path
|
||||
id="Combined-Shape"
|
||||
fill={theme.palette.primary.main}
|
||||
d="M30,21.3918362 C30,21.7535219 29.9019196,22.1084381 29.7162004,22.4188007 C29.1490236,23.366632 27.9208668,23.6752135 26.9730355,23.1080366 L26.9730355,23.1080366 L23.714971,21.1584295 C23.1114106,20.7972624 22.7419355,20.1455972 22.7419355,19.4422291 L22.7419355,19.4422291 L22.741,12.7425689 L15,17.1774194 L7.258,12.7425689 L7.25806452,19.4422291 C7.25806452,20.1455972 6.88858935,20.7972624 6.28502902,21.1584295 L3.0269645,23.1080366 C2.07913318,23.6752135 0.850976404,23.366632 0.283799571,22.4188007 C0.0980803893,22.1084381 2.0190442e-15,21.7535219 0,21.3918362 L0,3.58469444 L0.00548573643,3.43543209 L0.00548573643,3.43543209 L0,3.5715689 C3.0881846e-16,2.4669994 0.8954305,1.5715689 2,1.5715689 C2.36889529,1.5715689 2.73060353,1.67359571 3.04512412,1.86636639 L15,9.19354839 L26.9548759,1.86636639 C27.2693965,1.67359571 27.6311047,1.5715689 28,1.5715689 C29.1045695,1.5715689 30,2.4669994 30,3.5715689 L30,3.5715689 Z"
|
||||
/>
|
||||
<polygon
|
||||
id="Rectangle"
|
||||
opacity="0.077704"
|
||||
fill={theme.palette.common.black}
|
||||
points="0 8.58870968 7.25806452 12.7505183 7.25806452 16.8305646"
|
||||
/>
|
||||
<polygon
|
||||
id="Rectangle"
|
||||
opacity="0.077704"
|
||||
fill={theme.palette.common.black}
|
||||
points="0 8.58870968 7.25806452 12.6445567 7.25806452 15.1370162"
|
||||
/>
|
||||
<polygon
|
||||
id="Rectangle"
|
||||
opacity="0.077704"
|
||||
fill={theme.palette.common.black}
|
||||
points="22.7419355 8.58870968 30 12.7417372 30 16.9537453"
|
||||
transform="translate(26.370968, 12.771227) scale(-1, 1) translate(-26.370968, -12.771227) "
|
||||
/>
|
||||
<polygon
|
||||
id="Rectangle"
|
||||
opacity="0.077704"
|
||||
fill={theme.palette.common.black}
|
||||
points="22.7419355 8.58870968 30 12.6409734 30 15.2601969"
|
||||
transform="translate(26.370968, 11.924453) scale(-1, 1) translate(-26.370968, -11.924453) "
|
||||
/>
|
||||
<path
|
||||
id="Rectangle"
|
||||
fillOpacity="0.15"
|
||||
fill={theme.palette.common.white}
|
||||
d="M3.04512412,1.86636639 L15,9.19354839 L15,9.19354839 L15,17.1774194 L0,8.58649679 L0,3.5715689 C3.0881846e-16,2.4669994 0.8954305,1.5715689 2,1.5715689 C2.36889529,1.5715689 2.73060353,1.67359571 3.04512412,1.86636639 Z"
|
||||
/>
|
||||
<path
|
||||
id="Rectangle"
|
||||
fillOpacity="0.35"
|
||||
fill={theme.palette.common.white}
|
||||
transform="translate(22.500000, 8.588710) scale(-1, 1) translate(-22.500000, -8.588710) "
|
||||
d="M18.0451241,1.86636639 L30,9.19354839 L30,9.19354839 L30,17.1774194 L15,8.58649679 L15,3.5715689 C15,2.4669994 15.8954305,1.5715689 17,1.5715689 C17.3688953,1.5715689 17.7306035,1.67359571 18.0451241,1.86636639 Z"
|
||||
/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
<HeaderTitle variant="h6" sx={{ ml: 3 }}>
|
||||
{themeConfig.templateName}
|
||||
</HeaderTitle>
|
||||
</StyledLink>
|
||||
</Link>
|
||||
)}
|
||||
</MenuHeaderWrapper>
|
||||
);
|
||||
};
|
||||
|
||||
export default VerticalNavHeader;
|
@@ -0,0 +1,24 @@
|
||||
// ** Custom Menu Components
|
||||
import VerticalNavLink from './VerticalNavLink';
|
||||
import VerticalNavSectionTitle from './VerticalNavSectionTitle';
|
||||
|
||||
const resolveNavItemComponent = item => {
|
||||
if (item.sectionTitle) return VerticalNavSectionTitle;
|
||||
|
||||
return VerticalNavLink;
|
||||
};
|
||||
|
||||
const VerticalNavItems = props => {
|
||||
// ** Props
|
||||
const { verticalNavItems } = props;
|
||||
|
||||
const RenderMenuItems = verticalNavItems?.map((item, index) => {
|
||||
const TagName = resolveNavItemComponent(item);
|
||||
|
||||
return <TagName {...props} key={index} item={item} />;
|
||||
});
|
||||
|
||||
return <>{RenderMenuItems}</>;
|
||||
};
|
||||
|
||||
export default VerticalNavItems;
|
@@ -0,0 +1,119 @@
|
||||
// ** Next Imports
|
||||
import Link from 'next/link';
|
||||
import { useRouter } from 'next/router';
|
||||
|
||||
// ** MUI Imports
|
||||
import Chip from '@mui/material/Chip';
|
||||
import ListItem from '@mui/material/ListItem';
|
||||
import { styled } from '@mui/material/styles';
|
||||
import Typography from '@mui/material/Typography';
|
||||
import Box from '@mui/material/Box';
|
||||
import ListItemIcon from '@mui/material/ListItemIcon';
|
||||
import ListItemButton from '@mui/material/ListItemButton';
|
||||
|
||||
// ** Configs Import
|
||||
import themeConfig from 'src/configs/themeConfig';
|
||||
|
||||
// ** Custom Components Imports
|
||||
import UserIcon from 'src/layouts/components/UserIcon';
|
||||
|
||||
// ** Utils
|
||||
import { handleURLQueries } from 'src/@core/layouts/utils';
|
||||
|
||||
// ** Styled Components
|
||||
const MenuNavLink = styled(ListItemButton)(({ theme }) => ({
|
||||
width: '100%',
|
||||
borderTopRightRadius: 100,
|
||||
borderBottomRightRadius: 100,
|
||||
color: theme.palette.text.primary,
|
||||
padding: theme.spacing(2.25, 3.5),
|
||||
transition: 'opacity .25s ease-in-out',
|
||||
'&.active, &.active:hover': {
|
||||
boxShadow: theme.shadows[3],
|
||||
backgroundImage: `linear-gradient(98deg, ${theme.palette.customColors.primaryGradient}, ${theme.palette.primary.main} 94%)`,
|
||||
},
|
||||
'&.active .MuiTypography-root, &.active .MuiSvgIcon-root': {
|
||||
color: `${theme.palette.common.white} !important`,
|
||||
},
|
||||
}));
|
||||
|
||||
const MenuItemTextMetaWrapper = styled(Box)({
|
||||
width: '100%',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
transition: 'opacity .25s ease-in-out',
|
||||
...(themeConfig.menuTextTruncate && { overflow: 'hidden' }),
|
||||
});
|
||||
|
||||
const VerticalNavLink = ({ item, navVisible, toggleNavVisibility }) => {
|
||||
// ** Hooks
|
||||
const router = useRouter();
|
||||
const IconTag = item.icon;
|
||||
|
||||
const isNavLinkActive = () => {
|
||||
if (router.pathname === item.path || handleURLQueries(router, item.path)) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<ListItem
|
||||
disablePadding
|
||||
className="nav-link"
|
||||
disabled={item.disabled || false}
|
||||
sx={{ mt: 1.5, px: '0 !important' }}
|
||||
>
|
||||
<Link passHref href={item.path === undefined ? '/' : `${item.path}`}>
|
||||
<MenuNavLink
|
||||
component={'a'}
|
||||
className={isNavLinkActive() ? 'active' : ''}
|
||||
{...(item.openInNewTab ? { target: '_blank' } : null)}
|
||||
onClick={e => {
|
||||
if (item.path === undefined) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
}
|
||||
if (navVisible) {
|
||||
toggleNavVisibility();
|
||||
}
|
||||
}}
|
||||
sx={{
|
||||
pl: 5.5,
|
||||
...(item.disabled ? { pointerEvents: 'none' } : { cursor: 'pointer' }),
|
||||
}}
|
||||
>
|
||||
<ListItemIcon
|
||||
sx={{
|
||||
mr: 2.5,
|
||||
color: 'text.primary',
|
||||
transition: 'margin .25s ease-in-out',
|
||||
}}
|
||||
>
|
||||
<UserIcon icon={IconTag} />
|
||||
</ListItemIcon>
|
||||
|
||||
<MenuItemTextMetaWrapper>
|
||||
<Typography {...(themeConfig.menuTextTruncate && { noWrap: true })}>{item.title}</Typography>
|
||||
{item.badgeContent ? (
|
||||
<Chip
|
||||
label={item.badgeContent}
|
||||
color={item.badgeColor || 'primary'}
|
||||
sx={{
|
||||
height: 20,
|
||||
fontWeight: 500,
|
||||
marginLeft: 1.25,
|
||||
'& .MuiChip-label': { px: 1.5, textTransform: 'capitalize' },
|
||||
}}
|
||||
/>
|
||||
) : null}
|
||||
</MenuItemTextMetaWrapper>
|
||||
</MenuNavLink>
|
||||
</Link>
|
||||
</ListItem>
|
||||
);
|
||||
};
|
||||
|
||||
export default VerticalNavLink;
|
@@ -0,0 +1,63 @@
|
||||
// ** MUI Imports
|
||||
import Divider from '@mui/material/Divider';
|
||||
import { styled, useTheme } from '@mui/material/styles';
|
||||
import Typography from '@mui/material/Typography';
|
||||
import MuiListSubheader from '@mui/material/ListSubheader';
|
||||
|
||||
// ** Styled Components
|
||||
const ListSubheader = styled(props => <MuiListSubheader component="li" {...props} />)(({ theme }) => ({
|
||||
lineHeight: 1,
|
||||
display: 'flex',
|
||||
position: 'relative',
|
||||
marginTop: theme.spacing(7),
|
||||
marginBottom: theme.spacing(2),
|
||||
backgroundColor: 'transparent',
|
||||
transition: 'padding-left .25s ease-in-out',
|
||||
}));
|
||||
|
||||
const TypographyHeaderText = styled(Typography)(({ theme }) => ({
|
||||
fontSize: '0.75rem',
|
||||
lineHeight: 'normal',
|
||||
letterSpacing: '0.21px',
|
||||
textTransform: 'uppercase',
|
||||
color: theme.palette.text.disabled,
|
||||
fontWeight: theme.typography.fontWeightMedium,
|
||||
}));
|
||||
|
||||
const VerticalNavSectionTitle = props => {
|
||||
// ** Props
|
||||
const { item } = props;
|
||||
|
||||
// ** Hook
|
||||
const theme = useTheme();
|
||||
|
||||
return (
|
||||
<ListSubheader
|
||||
className="nav-section-title"
|
||||
sx={{
|
||||
px: 0,
|
||||
py: 1.75,
|
||||
color: theme.palette.text.disabled,
|
||||
'& .MuiDivider-root:before, & .MuiDivider-root:after, & hr': {
|
||||
borderColor: `rgba(${theme.palette.customColors.main}, 0.12)`,
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Divider
|
||||
textAlign="left"
|
||||
sx={{
|
||||
m: 0,
|
||||
width: '100%',
|
||||
lineHeight: 'normal',
|
||||
textTransform: 'uppercase',
|
||||
'&:before, &:after': { top: 7, transform: 'none' },
|
||||
'& .MuiDivider-wrapper': { px: 2.5, fontSize: '0.75rem', letterSpacing: '0.21px' },
|
||||
}}
|
||||
>
|
||||
<TypographyHeaderText noWrap>{item.sectionTitle}</TypographyHeaderText>
|
||||
</Divider>
|
||||
</ListSubheader>
|
||||
);
|
||||
};
|
||||
|
||||
export default VerticalNavSectionTitle;
|
@@ -0,0 +1,131 @@
|
||||
// ** React Import
|
||||
import { useRef, useState } from 'react';
|
||||
|
||||
// ** MUI Import
|
||||
import List from '@mui/material/List';
|
||||
import Box from '@mui/material/Box';
|
||||
import { styled, useTheme } from '@mui/material/styles';
|
||||
|
||||
// ** Third Party Components
|
||||
import PerfectScrollbar from 'react-perfect-scrollbar';
|
||||
|
||||
// ** Component Imports
|
||||
import Drawer from './Drawer';
|
||||
import VerticalNavItems from './VerticalNavItems';
|
||||
import VerticalNavHeader from './VerticalNavHeader';
|
||||
|
||||
// ** Util Import
|
||||
import { hexToRGBA } from 'src/@core/utils/hex-to-rgba';
|
||||
|
||||
const StyledBoxForShadow = styled(Box)({
|
||||
top: 50,
|
||||
left: -8,
|
||||
zIndex: 2,
|
||||
height: 75,
|
||||
display: 'none',
|
||||
position: 'absolute',
|
||||
pointerEvents: 'none',
|
||||
width: 'calc(100% + 15px)',
|
||||
'&.d-block': {
|
||||
display: 'block',
|
||||
},
|
||||
});
|
||||
|
||||
const Navigation = props => {
|
||||
// ** Props
|
||||
const {
|
||||
hidden,
|
||||
afterVerticalNavMenuContent,
|
||||
beforeVerticalNavMenuContent,
|
||||
verticalNavMenuContent: userVerticalNavMenuContent,
|
||||
} = props;
|
||||
|
||||
// ** States
|
||||
const [groupActive, setGroupActive] = useState([]);
|
||||
const [currentActiveGroup, setCurrentActiveGroup] = useState([]);
|
||||
|
||||
// ** Ref
|
||||
const shadowRef = useRef(null);
|
||||
|
||||
// ** Hooks
|
||||
const theme = useTheme();
|
||||
|
||||
// ** Fixes Navigation InfiniteScroll
|
||||
const handleInfiniteScroll = ref => {
|
||||
if (ref) {
|
||||
// @ts-ignore
|
||||
ref._getBoundingClientRect = ref.getBoundingClientRect;
|
||||
ref.getBoundingClientRect = () => {
|
||||
// @ts-ignore
|
||||
const original = ref._getBoundingClientRect();
|
||||
|
||||
return { ...original, height: Math.floor(original.height) };
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
// ** Scroll Menu
|
||||
const scrollMenu = container => {
|
||||
container = hidden ? container.target : container;
|
||||
if (shadowRef && container.scrollTop > 0) {
|
||||
// @ts-ignore
|
||||
if (!shadowRef.current.classList.contains('d-block')) {
|
||||
// @ts-ignore
|
||||
shadowRef.current.classList.add('d-block');
|
||||
}
|
||||
} else {
|
||||
// @ts-ignore
|
||||
shadowRef.current.classList.remove('d-block');
|
||||
}
|
||||
};
|
||||
const ScrollWrapper = hidden ? Box : PerfectScrollbar;
|
||||
|
||||
return (
|
||||
<Drawer {...props}>
|
||||
<VerticalNavHeader {...props} />
|
||||
<StyledBoxForShadow
|
||||
ref={shadowRef}
|
||||
sx={{
|
||||
background: `linear-gradient(${theme.palette.background.default} 40%,${hexToRGBA(
|
||||
theme.palette.background.default,
|
||||
0.1,
|
||||
)} 95%,${hexToRGBA(theme.palette.background.default, 0.05)})`,
|
||||
}}
|
||||
/>
|
||||
<Box sx={{ height: '100%', position: 'relative', overflow: 'hidden' }}>
|
||||
<ScrollWrapper
|
||||
containerRef={ref => handleInfiniteScroll(ref)}
|
||||
{...(hidden
|
||||
? {
|
||||
onScroll: container => scrollMenu(container),
|
||||
sx: { height: '100%', overflowY: 'auto', overflowX: 'hidden' },
|
||||
}
|
||||
: {
|
||||
options: { wheelPropagation: false },
|
||||
onScrollY: container => scrollMenu(container),
|
||||
})}
|
||||
>
|
||||
{beforeVerticalNavMenuContent ? beforeVerticalNavMenuContent(props) : null}
|
||||
<Box sx={{ height: '100%', display: 'flex', flexDirection: 'column', justifyContent: 'space-between' }}>
|
||||
{userVerticalNavMenuContent ? (
|
||||
userVerticalNavMenuContent(props)
|
||||
) : (
|
||||
<List className="nav-items" sx={{ transition: 'padding .25s ease', pr: 4.5 }}>
|
||||
<VerticalNavItems
|
||||
groupActive={groupActive}
|
||||
setGroupActive={setGroupActive}
|
||||
currentActiveGroup={currentActiveGroup}
|
||||
setCurrentActiveGroup={setCurrentActiveGroup}
|
||||
{...props}
|
||||
/>
|
||||
</List>
|
||||
)}
|
||||
</Box>
|
||||
</ScrollWrapper>
|
||||
</Box>
|
||||
{afterVerticalNavMenuContent ? afterVerticalNavMenuContent(props) : null}
|
||||
</Drawer>
|
||||
);
|
||||
};
|
||||
|
||||
export default Navigation;
|
16
tsc1877/task1/aws/workspace/admin/src/@core/layouts/utils.js
Normal file
16
tsc1877/task1/aws/workspace/admin/src/@core/layouts/utils.js
Normal file
@@ -0,0 +1,16 @@
|
||||
/**
|
||||
* Check for URL queries as well for matching
|
||||
* Current URL & Item Path
|
||||
*
|
||||
* @param item
|
||||
* @param activeItem
|
||||
*/
|
||||
export const handleURLQueries = (router, path) => {
|
||||
if (Object.keys(router.query).length && path) {
|
||||
const arr = Object.keys(router.query);
|
||||
|
||||
return router.asPath.includes(path) && router.asPath.includes(router.query[arr[0]]) && path !== '/';
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
103
tsc1877/task1/aws/workspace/admin/src/@core/styles/libs/react-apexcharts/index.js
vendored
Normal file
103
tsc1877/task1/aws/workspace/admin/src/@core/styles/libs/react-apexcharts/index.js
vendored
Normal file
@@ -0,0 +1,103 @@
|
||||
// ** MUI imports
|
||||
import { styled } from '@mui/material/styles';
|
||||
|
||||
const ApexChartWrapper = styled('div')(({ theme }) => ({
|
||||
'& .apexcharts-canvas': {
|
||||
"& line[stroke='transparent']": {
|
||||
display: 'none',
|
||||
},
|
||||
'& .apexcharts-xaxis > line, & .apexcharts-yaxis > line': {
|
||||
stroke: theme.palette.divider,
|
||||
},
|
||||
'& .apexcharts-xaxis-tick, & .apexcharts-yaxis-tick': {
|
||||
stroke: theme.palette.divider,
|
||||
},
|
||||
'& .apexcharts-tooltip': {
|
||||
boxShadow: theme.shadows[3],
|
||||
borderColor: theme.palette.divider,
|
||||
background: theme.palette.background.paper,
|
||||
'& .apexcharts-tooltip-title': {
|
||||
fontWeight: 600,
|
||||
borderColor: theme.palette.divider,
|
||||
background: theme.palette.background.paper,
|
||||
},
|
||||
'&.apexcharts-theme-dark': {
|
||||
'& .apexcharts-tooltip-text-label, & .apexcharts-tooltip-text-value': {
|
||||
color: theme.palette.common.white,
|
||||
},
|
||||
},
|
||||
'& .bar-chart': {
|
||||
padding: theme.spacing(2, 2.5),
|
||||
},
|
||||
},
|
||||
'& .apexcharts-xaxistooltip': {
|
||||
borderColor: theme.palette.divider,
|
||||
background: theme.palette.mode === 'light' ? theme.palette.grey[50] : theme.palette.background.default,
|
||||
'& .apexcharts-xaxistooltip-text': {
|
||||
color: theme.palette.text.primary,
|
||||
},
|
||||
'&:after': {
|
||||
borderBottomColor: theme.palette.mode === 'light' ? theme.palette.grey[50] : theme.palette.background.default,
|
||||
},
|
||||
'&:before': {
|
||||
borderBottomColor: theme.palette.divider,
|
||||
},
|
||||
},
|
||||
'& .apexcharts-yaxistooltip': {
|
||||
borderColor: theme.palette.divider,
|
||||
background: theme.palette.mode === 'light' ? theme.palette.grey[50] : theme.palette.background.default,
|
||||
'& .apexcharts-yaxistooltip-text': {
|
||||
color: theme.palette.text.primary,
|
||||
},
|
||||
'&:after': {
|
||||
borderLeftColor: theme.palette.mode === 'light' ? theme.palette.grey[50] : theme.palette.background.default,
|
||||
},
|
||||
'&:before': {
|
||||
borderLeftColor: theme.palette.divider,
|
||||
},
|
||||
},
|
||||
'& .apexcharts-text, & .apexcharts-tooltip-text, & .apexcharts-datalabel-label, & .apexcharts-datalabel': {
|
||||
filter: 'none',
|
||||
fontWeight: 400,
|
||||
fill: theme.palette.text.primary,
|
||||
fontFamily: `${theme.typography.fontFamily} !important`,
|
||||
},
|
||||
'& .apexcharts-pie-label': {
|
||||
filter: 'none',
|
||||
fill: theme.palette.common.white,
|
||||
},
|
||||
'& .apexcharts-pie': {
|
||||
'& .apexcharts-datalabel-label, .apexcharts-datalabel-value': {
|
||||
fontSize: '1.5rem',
|
||||
},
|
||||
},
|
||||
'& .apexcharts-marker': {
|
||||
boxShadow: 'none',
|
||||
},
|
||||
'& .apexcharts-legend-series': {
|
||||
margin: `${theme.spacing(0.75, 2)} !important`,
|
||||
'& .apexcharts-legend-text': {
|
||||
marginLeft: theme.spacing(0.75),
|
||||
color: `${theme.palette.text.primary} !important`,
|
||||
},
|
||||
},
|
||||
'& .apexcharts-xcrosshairs, & .apexcharts-ycrosshairs, & .apexcharts-gridline': {
|
||||
stroke: theme.palette.divider,
|
||||
},
|
||||
'& .apexcharts-heatmap-rect': {
|
||||
stroke: theme.palette.mode === 'light' ? theme.palette.background.paper : theme.palette.background.default,
|
||||
},
|
||||
'& .apexcharts-radialbar > g > g:first-of-type .apexcharts-radialbar-area': {
|
||||
stroke: theme.palette.background.default,
|
||||
},
|
||||
'& .apexcharts-radar-series polygon': {
|
||||
stroke: theme.palette.divider,
|
||||
fill: theme.palette.background.paper,
|
||||
},
|
||||
'& .apexcharts-radar-series line': {
|
||||
stroke: theme.palette.divider,
|
||||
},
|
||||
},
|
||||
}));
|
||||
|
||||
export default ApexChartWrapper;
|
358
tsc1877/task1/aws/workspace/admin/src/@core/styles/libs/react-datepicker/index.js
vendored
Normal file
358
tsc1877/task1/aws/workspace/admin/src/@core/styles/libs/react-datepicker/index.js
vendored
Normal file
@@ -0,0 +1,358 @@
|
||||
// ** MUI imports
|
||||
import { styled } from '@mui/material/styles';
|
||||
import Box from '@mui/material/Box';
|
||||
|
||||
// ** Util Import
|
||||
import { hexToRGBA } from 'src/@core/utils/hex-to-rgba';
|
||||
|
||||
const DatePickerWrapper = styled(Box)(({ theme }) => {
|
||||
return {
|
||||
'& .react-datepicker-popper': {
|
||||
zIndex: 5,
|
||||
},
|
||||
'& .react-datepicker-wrapper': {
|
||||
width: '100%',
|
||||
},
|
||||
'& .react-datepicker': {
|
||||
border: 'none',
|
||||
boxShadow: theme.shadows[7],
|
||||
padding: theme.spacing(2, 0),
|
||||
color: theme.palette.text.primary,
|
||||
borderRadius: theme.shape.borderRadius,
|
||||
fontFamily: theme.typography.fontFamily,
|
||||
backgroundColor: theme.palette.background.paper,
|
||||
'& .react-datepicker__header': {
|
||||
padding: 0,
|
||||
border: 'none',
|
||||
fontWeight: 'normal',
|
||||
backgroundColor: theme.palette.background.paper,
|
||||
'& .react-datepicker__day-name': {
|
||||
margin: 0,
|
||||
},
|
||||
},
|
||||
'& .react-datepicker-year-header': {
|
||||
lineHeight: 2.1,
|
||||
marginBottom: '0.5rem',
|
||||
color: theme.palette.text.primary,
|
||||
},
|
||||
'& .react-datepicker__triangle': {
|
||||
display: 'none',
|
||||
},
|
||||
'& > .react-datepicker__navigation': {
|
||||
top: theme.spacing(3),
|
||||
'&.react-datepicker__navigation--previous': {
|
||||
border: 'none',
|
||||
backgroundImage: `${"url('data:image/svg+xml,%3Csvg xmlns=\\'http://www.w3.org/2000/svg\\' style=\\'width:24px;height:24px\\' viewBox=\\'0 0 24 24\\'%3E%3Cpath fill=\\'currentColor\\' d=\\'M15.41,16.58L10.83,12L15.41,7.41L14,6L8,12L14,18L15.41,16.58Z\\' /%3E%3C/svg%3E')"
|
||||
.replace('currentColor', theme.palette.text.secondary)
|
||||
.replace('#', '%23')}`,
|
||||
height: '24px',
|
||||
width: '24px',
|
||||
'& .react-datepicker__navigation-icon': {
|
||||
display: 'none',
|
||||
},
|
||||
},
|
||||
'&.react-datepicker__navigation--next': {
|
||||
border: 'none',
|
||||
backgroundImage: `${"url('data:image/svg+xml,%3Csvg xmlns=\\'http://www.w3.org/2000/svg\\' style=\\'width:24px;height:24px\\' viewBox=\\'0 0 24 24\\'%3E%3Cpath fill=\\'currentColor\\' d=\\'M8.59,16.58L13.17,12L8.59,7.41L10,6L16,12L10,18L8.59,16.58Z\\' /%3E%3C/svg%3E')"
|
||||
.replace('currentColor', theme.palette.text.secondary)
|
||||
.replace('#', '%23')}`,
|
||||
height: '24px',
|
||||
width: '24px',
|
||||
'& .react-datepicker__navigation-icon': {
|
||||
display: 'none',
|
||||
},
|
||||
},
|
||||
'&.react-datepicker__navigation--next--with-time': {
|
||||
right: '122px',
|
||||
},
|
||||
'&:focus, &:active': {
|
||||
outline: 0,
|
||||
},
|
||||
},
|
||||
'& .react-datepicker__current-month': {
|
||||
lineHeight: 2.1,
|
||||
fontSize: '1rem',
|
||||
fontWeight: 'normal',
|
||||
letterSpacing: '0.15px',
|
||||
marginBottom: theme.spacing(2),
|
||||
color: theme.palette.text.primary,
|
||||
},
|
||||
'& .react-datepicker__day-name': {
|
||||
lineHeight: 1.5,
|
||||
width: '2.25rem',
|
||||
fontSize: '0.75rem',
|
||||
letterSpacing: '0.4px',
|
||||
color: theme.palette.text.secondary,
|
||||
},
|
||||
'& .react-datepicker__day': {
|
||||
margin: 0,
|
||||
width: '2.25rem',
|
||||
lineHeight: 2.75,
|
||||
height: '2.25rem',
|
||||
borderRadius: '50%',
|
||||
color: theme.palette.text.primary,
|
||||
'&.react-datepicker__day--selected, &.react-datepicker__day--keyboard-selected': {
|
||||
color: theme.palette.common.white,
|
||||
backgroundColor: `${theme.palette.primary.main} !important`,
|
||||
},
|
||||
'&.react-datepicker__day--in-range, &.react-datepicker__day--in-selecting-range': {
|
||||
borderRadius: 0,
|
||||
color: theme.palette.primary.main,
|
||||
backgroundColor: `${hexToRGBA(theme.palette.primary.main, 0.06)} !important`,
|
||||
'&:empty': {
|
||||
backgroundColor: 'transparent !important',
|
||||
},
|
||||
},
|
||||
'&.react-datepicker__day--selected.react-datepicker__day--in-selecting-range.react-datepicker__day--selecting-range-start, &.react-datepicker__day--selected.react-datepicker__day--range-start.react-datepicker__day--in-range, &.react-datepicker__day--range-start':
|
||||
{
|
||||
borderTopLeftRadius: '50%',
|
||||
borderBottomLeftRadius: '50%',
|
||||
color: theme.palette.common.white,
|
||||
backgroundColor: `${theme.palette.primary.main} !important`,
|
||||
},
|
||||
'&.react-datepicker__day--range-end': {
|
||||
borderTopRightRadius: '50%',
|
||||
borderBottomRightRadius: '50%',
|
||||
color: theme.palette.common.white,
|
||||
backgroundColor: `${theme.palette.primary.main} !important`,
|
||||
},
|
||||
'&:focus, &:active': {
|
||||
outline: 0,
|
||||
},
|
||||
'&.react-datepicker__day--outside-month': {
|
||||
height: 'auto',
|
||||
},
|
||||
'&.react-datepicker__day--outside-month, &.react-datepicker__day--disabled:not(.react-datepicker__day--selected)':
|
||||
{
|
||||
color: theme.palette.text.disabled,
|
||||
'&:hover': {
|
||||
backgroundColor: 'transparent',
|
||||
},
|
||||
},
|
||||
'&.react-datepicker__day--highlighted, &.react-datepicker__day--highlighted:hover': {
|
||||
color: theme.palette.success.main,
|
||||
backgroundColor: hexToRGBA(theme.palette.success.main, 0.12),
|
||||
},
|
||||
'&.react-datepicker__day--today': {
|
||||
fontWeight: 'normal',
|
||||
},
|
||||
},
|
||||
'& .react-datepicker__header__dropdown': {
|
||||
'& .react-datepicker__month-dropdown-container:not(:last-child)': {
|
||||
marginRight: theme.spacing(8),
|
||||
},
|
||||
'& .react-datepicker__month-dropdown-container, & .react-datepicker__year-dropdown-container': {
|
||||
marginBottom: theme.spacing(4),
|
||||
},
|
||||
'& .react-datepicker__month-read-view--selected-month, & .react-datepicker__year-read-view--selected-year': {
|
||||
fontSize: '0.875rem',
|
||||
marginRight: theme.spacing(1),
|
||||
color: theme.palette.text.primary,
|
||||
},
|
||||
'& .react-datepicker__month-read-view:hover .react-datepicker__month-read-view--down-arrow, & .react-datepicker__year-read-view:hover .react-datepicker__year-read-view--down-arrow':
|
||||
{
|
||||
borderTopColor: theme.palette.text.secondary,
|
||||
borderRightColor: theme.palette.text.secondary,
|
||||
},
|
||||
'& .react-datepicker__month-read-view--down-arrow, & .react-datepicker__year-read-view--down-arrow': {
|
||||
top: 4,
|
||||
borderTopColor: theme.palette.text.disabled,
|
||||
borderRightColor: theme.palette.text.disabled,
|
||||
},
|
||||
'& .react-datepicker__month-dropdown, & .react-datepicker__year-dropdown': {
|
||||
paddingTop: theme.spacing(1.5),
|
||||
paddingBottom: theme.spacing(1.5),
|
||||
borderColor: theme.palette.divider,
|
||||
borderRadius: theme.shape.borderRadius,
|
||||
backgroundColor: theme.palette.background.paper,
|
||||
boxShadow: theme.palette.mode === 'light' ? theme.shadows[8] : theme.shadows[9],
|
||||
},
|
||||
'& .react-datepicker__month-option, & .react-datepicker__year-option': {
|
||||
paddingTop: theme.spacing(0.5),
|
||||
paddingBottom: theme.spacing(0.5),
|
||||
'&:hover': {
|
||||
backgroundColor: theme.palette.action.hover,
|
||||
},
|
||||
},
|
||||
'& .react-datepicker__month-option.react-datepicker__month-option--selected_month': {
|
||||
backgroundColor: hexToRGBA(theme.palette.primary.main, 0.08),
|
||||
'&:hover': {
|
||||
backgroundColor: hexToRGBA(theme.palette.primary.main, 0.12),
|
||||
},
|
||||
'& .react-datepicker__month-option--selected': {
|
||||
display: 'none',
|
||||
},
|
||||
},
|
||||
'& .react-datepicker__year-option.react-datepicker__year-option--selected_year': {
|
||||
backgroundColor: hexToRGBA(theme.palette.primary.main, 0.08),
|
||||
'&:hover': {
|
||||
backgroundColor: hexToRGBA(theme.palette.primary.main, 0.12),
|
||||
},
|
||||
'& .react-datepicker__year-option--selected': {
|
||||
display: 'none',
|
||||
},
|
||||
},
|
||||
'& .react-datepicker__year-option': {
|
||||
// TODO: Remove some of the following styles for arrow in Year dropdown when react-datepicker give arrows in Year dropdown
|
||||
'& .react-datepicker__navigation--years-upcoming': {
|
||||
width: 9,
|
||||
height: 9,
|
||||
borderStyle: 'solid',
|
||||
borderWidth: '3px 3px 0 0',
|
||||
transform: 'rotate(-45deg)',
|
||||
borderTopColor: theme.palette.text.disabled,
|
||||
borderRightColor: theme.palette.text.disabled,
|
||||
margin: `${theme.spacing(2.75)} auto ${theme.spacing(0)}`,
|
||||
},
|
||||
'&:hover .react-datepicker__navigation--years-upcoming': {
|
||||
borderTopColor: theme.palette.text.secondary,
|
||||
borderRightColor: theme.palette.text.secondary,
|
||||
},
|
||||
'& .react-datepicker__navigation--years-previous': {
|
||||
width: 9,
|
||||
height: 9,
|
||||
borderStyle: 'solid',
|
||||
borderWidth: '0 0 3px 3px',
|
||||
transform: 'rotate(-45deg)',
|
||||
borderLeftColor: theme.palette.text.disabled,
|
||||
borderBottomColor: theme.palette.text.disabled,
|
||||
margin: `${theme.spacing(0)} auto ${theme.spacing(2.75)}`,
|
||||
},
|
||||
'&:hover .react-datepicker__navigation--years-previous': {
|
||||
borderLeftColor: theme.palette.text.secondary,
|
||||
borderBottomColor: theme.palette.text.secondary,
|
||||
},
|
||||
},
|
||||
},
|
||||
'& .react-datepicker__month': {
|
||||
marginTop: theme.spacing(3),
|
||||
},
|
||||
[theme.breakpoints.down('sm')]: {
|
||||
'& .react-datepicker__month': {
|
||||
marginLeft: 0,
|
||||
marginRight: 0,
|
||||
marginBottom: 0,
|
||||
},
|
||||
},
|
||||
'& .react-datepicker__month, & .react-datepicker__year': {
|
||||
'& .react-datepicker__month-text, & .react-datepicker__year-text, & .react-datepicker__quarter-text': {
|
||||
height: '2rem',
|
||||
alignItems: 'center',
|
||||
display: 'inline-flex',
|
||||
justifyContent: 'center',
|
||||
'&:hover': {
|
||||
borderRadius: theme.shape.borderRadius,
|
||||
},
|
||||
'&:focus, &:active': {
|
||||
outline: 0,
|
||||
},
|
||||
},
|
||||
'& .react-datepicker__quarter--selected, & .react-datepicker__year-text--selected, & .react-datepicker__month--selected, & .react-datepicker__quarter-text--keyboard-selected, & .react-datepicker__month-text--keyboard-selected, & .react-datepicker__year-text--keyboard-selected':
|
||||
{
|
||||
color: theme.palette.common.white,
|
||||
borderRadius: theme.shape.borderRadius,
|
||||
backgroundColor: `${theme.palette.primary.main} !important`,
|
||||
},
|
||||
'& .react-datepicker__week-number': {
|
||||
fontWeight: 600,
|
||||
color: theme.palette.text.primary,
|
||||
},
|
||||
},
|
||||
'& .react-datepicker__year-wrapper': {
|
||||
maxWidth: 205,
|
||||
justifyContent: 'center',
|
||||
},
|
||||
'& .react-datepicker__input-time-container': {
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
},
|
||||
'& .react-datepicker__today-button': {
|
||||
borderRadius: '1rem',
|
||||
margin: '0 1rem 0.3rem',
|
||||
color: theme.palette.common.white,
|
||||
backgroundColor: theme.palette.primary.main,
|
||||
},
|
||||
|
||||
// ** Time Picker
|
||||
'& .react-datepicker__time-container': {
|
||||
borderLeftColor: theme.palette.divider,
|
||||
},
|
||||
'&.react-datepicker--time-only, & .react-datepicker__time-container': {
|
||||
width: '7rem',
|
||||
padding: theme.spacing(1.2, 0),
|
||||
'& .react-datepicker-time__header': {
|
||||
marginBottom: theme.spacing(3),
|
||||
color: theme.palette.text.primary,
|
||||
fontSize: theme.typography.body2.fontSize,
|
||||
},
|
||||
'& .react-datepicker__time': {
|
||||
background: theme.palette.background.paper,
|
||||
'& .react-datepicker__time-box .react-datepicker__time-list-item--disabled': {
|
||||
color: theme.palette.text.disabled,
|
||||
},
|
||||
},
|
||||
'& .react-datepicker__time-list-item': {
|
||||
lineHeight: 1.75,
|
||||
height: 'auto !important',
|
||||
marginLeft: theme.spacing(3.2),
|
||||
marginRight: theme.spacing(1.2),
|
||||
color: theme.palette.text.primary,
|
||||
borderRadius: theme.shape.borderRadius,
|
||||
'&:focus, &:active': {
|
||||
outline: 0,
|
||||
},
|
||||
'&:hover': {
|
||||
backgroundColor: `${theme.palette.action.hover} !important`,
|
||||
},
|
||||
'&.react-datepicker__time-list-item--selected': {
|
||||
color: `${theme.palette.common.white} !important`,
|
||||
backgroundColor: `${theme.palette.primary.main} !important`,
|
||||
},
|
||||
},
|
||||
'& .react-datepicker__time-box': {
|
||||
width: '100%',
|
||||
},
|
||||
'& .react-datepicker__time-list': {
|
||||
'&::-webkit-scrollbar': {
|
||||
width: 8,
|
||||
},
|
||||
|
||||
/* Track */
|
||||
'&::-webkit-scrollbar-track': {
|
||||
background: theme.palette.background.paper,
|
||||
},
|
||||
|
||||
/* Handle */
|
||||
'&::-webkit-scrollbar-thumb': {
|
||||
background: '#aaa',
|
||||
borderRadius: '10px',
|
||||
},
|
||||
|
||||
/* Handle on hover */
|
||||
'&::-webkit-scrollbar-thumb:hover': {
|
||||
background: '#999',
|
||||
},
|
||||
},
|
||||
},
|
||||
'&.react-datepicker--time-only .react-datepicker__time-container': {
|
||||
width: 'calc(7rem - 2px)',
|
||||
},
|
||||
'& .react-datepicker__day:hover, & .react-datepicker__month-text:hover, & .react-datepicker__quarter-text:hover, & .react-datepicker__year-text:hover':
|
||||
{
|
||||
backgroundColor: theme.palette.action.hover,
|
||||
},
|
||||
},
|
||||
'& .react-datepicker__close-icon': {
|
||||
paddingRight: theme.spacing(4),
|
||||
'&:after': {
|
||||
width: 'unset',
|
||||
height: 'unset',
|
||||
fontSize: '1.5rem',
|
||||
color: theme.palette.text.primary,
|
||||
backgroundColor: 'transparent !important',
|
||||
},
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
export default DatePickerWrapper;
|
@@ -0,0 +1,49 @@
|
||||
// ** MUI Imports
|
||||
import CssBaseline from '@mui/material/CssBaseline';
|
||||
import GlobalStyles from '@mui/material/GlobalStyles';
|
||||
import { ThemeProvider, createTheme, responsiveFontSizes } from '@mui/material/styles';
|
||||
|
||||
// ** Theme Config
|
||||
import themeConfig from 'src/configs/themeConfig';
|
||||
|
||||
// ** Theme Override Imports
|
||||
import overrides from './overrides';
|
||||
import typography from './typography';
|
||||
|
||||
// ** Theme
|
||||
import themeOptions from './ThemeOptions';
|
||||
|
||||
// ** Global Styles
|
||||
import GlobalStyling from './globalStyles';
|
||||
|
||||
const ThemeComponent = props => {
|
||||
// ** Props
|
||||
const { settings, children } = props;
|
||||
|
||||
// ** Merged ThemeOptions of Core and User
|
||||
const coreThemeConfig = themeOptions(settings);
|
||||
|
||||
// ** Pass ThemeOptions to CreateTheme Function to create partial theme without component overrides
|
||||
let theme = createTheme(coreThemeConfig);
|
||||
|
||||
// ** Continue theme creation and pass merged component overrides to CreateTheme function
|
||||
theme = createTheme(theme, {
|
||||
components: { ...overrides(theme) },
|
||||
typography: { ...typography(theme) },
|
||||
});
|
||||
|
||||
// ** Set responsive font sizes to true
|
||||
if (themeConfig.responsiveFontSizes) {
|
||||
theme = responsiveFontSizes(theme);
|
||||
}
|
||||
|
||||
return (
|
||||
<ThemeProvider theme={theme}>
|
||||
<CssBaseline />
|
||||
<GlobalStyles styles={() => GlobalStyling(theme)} />
|
||||
{children}
|
||||
</ThemeProvider>
|
||||
);
|
||||
};
|
||||
|
||||
export default ThemeComponent;
|
@@ -0,0 +1,54 @@
|
||||
// ** MUI Theme Provider
|
||||
import { deepmerge } from '@mui/utils';
|
||||
|
||||
// ** Theme Override Imports
|
||||
import palette from './palette';
|
||||
import spacing from './spacing';
|
||||
import shadows from './shadows';
|
||||
import breakpoints from './breakpoints';
|
||||
|
||||
const themeOptions = settings => {
|
||||
// ** Vars
|
||||
const { mode, themeColor } = settings;
|
||||
|
||||
const themeConfig = {
|
||||
palette: palette(mode, themeColor),
|
||||
typography: {
|
||||
fontFamily: [
|
||||
'Inter',
|
||||
'sans-serif',
|
||||
'-apple-system',
|
||||
'BlinkMacSystemFont',
|
||||
'"Segoe UI"',
|
||||
'Roboto',
|
||||
'"Helvetica Neue"',
|
||||
'Arial',
|
||||
'sans-serif',
|
||||
'"Apple Color Emoji"',
|
||||
'"Segoe UI Emoji"',
|
||||
'"Segoe UI Symbol"',
|
||||
].join(','),
|
||||
},
|
||||
shadows: shadows(mode),
|
||||
...spacing,
|
||||
breakpoints: breakpoints(),
|
||||
shape: {
|
||||
borderRadius: 6,
|
||||
},
|
||||
mixins: {
|
||||
toolbar: {
|
||||
minHeight: 64,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
return deepmerge(themeConfig, {
|
||||
palette: {
|
||||
primary: {
|
||||
...themeConfig.palette[themeColor],
|
||||
},
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
export default themeOptions;
|
@@ -0,0 +1,11 @@
|
||||
const breakpoints = () => ({
|
||||
values: {
|
||||
xs: 0,
|
||||
sm: 600,
|
||||
md: 900,
|
||||
lg: 1200,
|
||||
xl: 1536,
|
||||
},
|
||||
});
|
||||
|
||||
export default breakpoints;
|
@@ -0,0 +1,43 @@
|
||||
const GlobalStyles = theme => {
|
||||
return {
|
||||
'.ps__rail-y': {
|
||||
zIndex: 1,
|
||||
right: '0 !important',
|
||||
left: 'auto !important',
|
||||
'&:hover, &:focus, &.ps--clicking': {
|
||||
backgroundColor: theme.palette.mode === 'light' ? '#E4E5EB !important' : '#423D5D !important',
|
||||
},
|
||||
'& .ps__thumb-y': {
|
||||
right: '3px !important',
|
||||
left: 'auto !important',
|
||||
backgroundColor: theme.palette.mode === 'light' ? '#C2C4D1 !important' : '#504B6D !important',
|
||||
},
|
||||
'.layout-vertical-nav &': {
|
||||
'& .ps__thumb-y': {
|
||||
width: 4,
|
||||
backgroundColor: theme.palette.mode === 'light' ? '#C2C4D1 !important' : '#504B6D !important',
|
||||
},
|
||||
'&:hover, &:focus, &.ps--clicking': {
|
||||
backgroundColor: 'transparent !important',
|
||||
'& .ps__thumb-y': {
|
||||
width: 6,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
'#nprogress': {
|
||||
pointerEvents: 'none',
|
||||
'& .bar': {
|
||||
left: 0,
|
||||
top: 0,
|
||||
height: 3,
|
||||
width: '100%',
|
||||
zIndex: 2000,
|
||||
position: 'fixed',
|
||||
backgroundColor: theme.palette.primary.main,
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export default GlobalStyles;
|
@@ -0,0 +1,46 @@
|
||||
const Accordion = theme => {
|
||||
return {
|
||||
MuiAccordion: {
|
||||
styleOverrides: {
|
||||
root: {
|
||||
'&.Mui-disabled': {
|
||||
backgroundColor: `rgba(${theme.palette.customColors.main}, 0.12)`,
|
||||
},
|
||||
'&.Mui-expanded': {
|
||||
boxShadow: theme.shadows[3],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
MuiAccordionSummary: {
|
||||
styleOverrides: {
|
||||
root: {
|
||||
padding: `0 ${theme.spacing(5)}`,
|
||||
'& + .MuiCollapse-root': {
|
||||
'& .MuiAccordionDetails-root:first-child': {
|
||||
paddingTop: 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
content: {
|
||||
margin: `${theme.spacing(2.5)} 0`,
|
||||
},
|
||||
expandIconWrapper: {
|
||||
color: theme.palette.text.secondary,
|
||||
},
|
||||
},
|
||||
},
|
||||
MuiAccordionDetails: {
|
||||
styleOverrides: {
|
||||
root: {
|
||||
padding: theme.spacing(5),
|
||||
'& + .MuiAccordionDetails-root': {
|
||||
paddingTop: 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export default Accordion;
|
@@ -0,0 +1,110 @@
|
||||
import { lighten, darken } from '@mui/material/styles';
|
||||
|
||||
// ** Util Import
|
||||
import { hexToRGBA } from 'src/@core/utils/hex-to-rgba';
|
||||
|
||||
const Alert = theme => {
|
||||
const getColor = theme.palette.mode === 'light' ? darken : lighten;
|
||||
|
||||
return {
|
||||
MuiAlert: {
|
||||
styleOverrides: {
|
||||
root: {
|
||||
borderRadius: 5,
|
||||
'& .MuiAlertTitle-root': {
|
||||
marginBottom: theme.spacing(1.6),
|
||||
},
|
||||
'& a': {
|
||||
color: 'inherit',
|
||||
fontWeight: 500,
|
||||
},
|
||||
},
|
||||
standardSuccess: {
|
||||
color: getColor(theme.palette.success.main, 0.12),
|
||||
backgroundColor: hexToRGBA(theme.palette.success.main, 0.12),
|
||||
'& .MuiAlertTitle-root': {
|
||||
color: getColor(theme.palette.success.main, 0.12),
|
||||
},
|
||||
'& .MuiAlert-icon': {
|
||||
color: getColor(theme.palette.success.main, 0.12),
|
||||
},
|
||||
},
|
||||
standardInfo: {
|
||||
color: getColor(theme.palette.info.main, 0.12),
|
||||
backgroundColor: hexToRGBA(theme.palette.info.main, 0.12),
|
||||
'& .MuiAlertTitle-root': {
|
||||
color: getColor(theme.palette.info.main, 0.12),
|
||||
},
|
||||
'& .MuiAlert-icon': {
|
||||
color: getColor(theme.palette.info.main, 0.12),
|
||||
},
|
||||
},
|
||||
standardWarning: {
|
||||
color: getColor(theme.palette.warning.main, 0.12),
|
||||
backgroundColor: hexToRGBA(theme.palette.warning.main, 0.12),
|
||||
'& .MuiAlertTitle-root': {
|
||||
color: getColor(theme.palette.warning.main, 0.12),
|
||||
},
|
||||
'& .MuiAlert-icon': {
|
||||
color: getColor(theme.palette.warning.main, 0.12),
|
||||
},
|
||||
},
|
||||
standardError: {
|
||||
color: getColor(theme.palette.error.main, 0.12),
|
||||
backgroundColor: hexToRGBA(theme.palette.error.main, 0.12),
|
||||
'& .MuiAlertTitle-root': {
|
||||
color: getColor(theme.palette.error.main, 0.12),
|
||||
},
|
||||
'& .MuiAlert-icon': {
|
||||
color: getColor(theme.palette.error.main, 0.12),
|
||||
},
|
||||
},
|
||||
outlinedSuccess: {
|
||||
borderColor: theme.palette.success.main,
|
||||
color: getColor(theme.palette.success.main, 0.12),
|
||||
'& .MuiAlertTitle-root': {
|
||||
color: getColor(theme.palette.success.main, 0.12),
|
||||
},
|
||||
'& .MuiAlert-icon': {
|
||||
color: getColor(theme.palette.success.main, 0.12),
|
||||
},
|
||||
},
|
||||
outlinedInfo: {
|
||||
borderColor: theme.palette.info.main,
|
||||
color: getColor(theme.palette.info.main, 0.12),
|
||||
'& .MuiAlertTitle-root': {
|
||||
color: getColor(theme.palette.info.main, 0.12),
|
||||
},
|
||||
'& .MuiAlert-icon': {
|
||||
color: getColor(theme.palette.info.main, 0.12),
|
||||
},
|
||||
},
|
||||
outlinedWarning: {
|
||||
borderColor: theme.palette.warning.main,
|
||||
color: getColor(theme.palette.warning.main, 0.12),
|
||||
'& .MuiAlertTitle-root': {
|
||||
color: getColor(theme.palette.warning.main, 0.12),
|
||||
},
|
||||
'& .MuiAlert-icon': {
|
||||
color: getColor(theme.palette.warning.main, 0.12),
|
||||
},
|
||||
},
|
||||
outlinedError: {
|
||||
borderColor: theme.palette.error.main,
|
||||
color: getColor(theme.palette.error.main, 0.12),
|
||||
'& .MuiAlertTitle-root': {
|
||||
color: getColor(theme.palette.error.main, 0.12),
|
||||
},
|
||||
'& .MuiAlert-icon': {
|
||||
color: getColor(theme.palette.error.main, 0.12),
|
||||
},
|
||||
},
|
||||
filled: {
|
||||
fontWeight: 400,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export default Alert;
|
@@ -0,0 +1,27 @@
|
||||
const Avatar = theme => {
|
||||
return {
|
||||
MuiAvatar: {
|
||||
styleOverrides: {
|
||||
colorDefault: {
|
||||
color: theme.palette.text.secondary,
|
||||
backgroundColor: theme.palette.mode === 'light' ? theme.palette.grey[200] : theme.palette.grey[700],
|
||||
},
|
||||
rounded: {
|
||||
borderRadius: 5,
|
||||
},
|
||||
},
|
||||
},
|
||||
MuiAvatarGroup: {
|
||||
styleOverrides: {
|
||||
root: {
|
||||
justifyContent: 'flex-end',
|
||||
'.MuiCard-root & .MuiAvatar-root': {
|
||||
borderColor: theme.palette.background.paper,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export default Avatar;
|
@@ -0,0 +1,22 @@
|
||||
// ** Util Import
|
||||
import { hexToRGBA } from 'src/@core/utils/hex-to-rgba';
|
||||
|
||||
const Backdrop = theme => {
|
||||
return {
|
||||
MuiBackdrop: {
|
||||
styleOverrides: {
|
||||
root: {
|
||||
backgroundColor:
|
||||
theme.palette.mode === 'light'
|
||||
? `rgba(${theme.palette.customColors.main}, 0.7)`
|
||||
: hexToRGBA(theme.palette.background.default, 0.7),
|
||||
},
|
||||
invisible: {
|
||||
backgroundColor: 'transparent',
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export default Backdrop;
|
@@ -0,0 +1,50 @@
|
||||
// ** Theme Config Imports
|
||||
import themeConfig from 'src/configs/themeConfig';
|
||||
|
||||
const Button = theme => {
|
||||
return {
|
||||
MuiButton: {
|
||||
styleOverrides: {
|
||||
root: {
|
||||
fontWeight: 500,
|
||||
borderRadius: 5,
|
||||
lineHeight: 1.71,
|
||||
letterSpacing: '0.3px',
|
||||
padding: `${theme.spacing(1.875, 3)}`,
|
||||
},
|
||||
contained: {
|
||||
boxShadow: theme.shadows[3],
|
||||
padding: `${theme.spacing(1.875, 5.5)}`,
|
||||
},
|
||||
outlined: {
|
||||
padding: `${theme.spacing(1.625, 5.25)}`,
|
||||
},
|
||||
sizeSmall: {
|
||||
padding: `${theme.spacing(1, 2.25)}`,
|
||||
'&.MuiButton-contained': {
|
||||
padding: `${theme.spacing(1, 3.5)}`,
|
||||
},
|
||||
'&.MuiButton-outlined': {
|
||||
padding: `${theme.spacing(0.75, 3.25)}`,
|
||||
},
|
||||
},
|
||||
sizeLarge: {
|
||||
padding: `${theme.spacing(2.125, 5.5)}`,
|
||||
'&.MuiButton-contained': {
|
||||
padding: `${theme.spacing(2.125, 6.5)}`,
|
||||
},
|
||||
'&.MuiButton-outlined': {
|
||||
padding: `${theme.spacing(1.875, 6.25)}`,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
MuiButtonBase: {
|
||||
defaultProps: {
|
||||
disableRipple: themeConfig.disableRipple,
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export default Button;
|
@@ -0,0 +1,83 @@
|
||||
const Card = theme => {
|
||||
return {
|
||||
MuiCard: {
|
||||
styleOverrides: {
|
||||
root: {
|
||||
boxShadow: theme.shadows[6],
|
||||
'& .card-more-options': {
|
||||
marginTop: theme.spacing(-1),
|
||||
marginRight: theme.spacing(-3),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
MuiCardHeader: {
|
||||
styleOverrides: {
|
||||
root: {
|
||||
padding: theme.spacing(5),
|
||||
'& + .MuiCardContent-root, & + .MuiCollapse-root .MuiCardContent-root': {
|
||||
paddingTop: 0,
|
||||
},
|
||||
'& .MuiCardHeader-subheader': {
|
||||
fontSize: '0.875rem',
|
||||
},
|
||||
},
|
||||
title: {
|
||||
lineHeight: 1,
|
||||
fontWeight: 500,
|
||||
fontSize: '1.25rem',
|
||||
letterSpacing: '0.0125em',
|
||||
},
|
||||
action: {
|
||||
marginTop: 0,
|
||||
marginRight: 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
MuiCardContent: {
|
||||
styleOverrides: {
|
||||
root: {
|
||||
padding: theme.spacing(5),
|
||||
'& + .MuiCardContent-root': {
|
||||
paddingTop: 0,
|
||||
},
|
||||
'&:last-of-type': {
|
||||
paddingBottom: theme.spacing(5),
|
||||
},
|
||||
'& + .MuiCardActions-root': {
|
||||
paddingTop: 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
MuiCardActions: {
|
||||
styleOverrides: {
|
||||
root: {
|
||||
padding: theme.spacing(5),
|
||||
'&.card-action-dense': {
|
||||
padding: theme.spacing(0, 2.5, 2.5),
|
||||
'.MuiCard-root .MuiCardMedia-root + &': {
|
||||
paddingTop: theme.spacing(2.5),
|
||||
},
|
||||
'.MuiCard-root &:first-of-type': {
|
||||
paddingTop: theme.spacing(5),
|
||||
paddingBottom: theme.spacing(5),
|
||||
'& + .MuiCardContent-root': {
|
||||
paddingTop: 0,
|
||||
},
|
||||
'& + .MuiCardHeader-root': {
|
||||
paddingTop: 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
'& .MuiButton-text': {
|
||||
paddingLeft: theme.spacing(2.5),
|
||||
paddingRight: theme.spacing(2.5),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export default Card;
|
@@ -0,0 +1,19 @@
|
||||
const Chip = theme => {
|
||||
return {
|
||||
MuiChip: {
|
||||
styleOverrides: {
|
||||
outlined: {
|
||||
'&.MuiChip-colorDefault': {
|
||||
borderColor: `rgba(${theme.palette.customColors.main}, 0.22)`,
|
||||
},
|
||||
},
|
||||
deleteIcon: {
|
||||
width: 18,
|
||||
height: 18,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export default Chip;
|
@@ -0,0 +1,61 @@
|
||||
const DateTimePicker = theme => {
|
||||
return {
|
||||
MuiCalendarPicker: {
|
||||
styleOverrides: {
|
||||
root: {
|
||||
'& [role="presentation"]': {
|
||||
fontWeight: 400,
|
||||
'& .PrivatePickersFadeTransitionGroup-root + .PrivatePickersFadeTransitionGroup-root > div': {
|
||||
marginRight: 0,
|
||||
},
|
||||
'& .MuiIconButton-sizeSmall': {
|
||||
padding: theme.spacing(0.5),
|
||||
},
|
||||
'& + div .MuiIconButton-root:not(.Mui-disabled)': {
|
||||
color: theme.palette.text.secondary,
|
||||
},
|
||||
},
|
||||
'& .PrivatePickersSlideTransition-root': {
|
||||
minHeight: 240,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
MuiPickersDay: {
|
||||
styleOverrides: {
|
||||
root: {
|
||||
fontSize: '0.875rem',
|
||||
},
|
||||
},
|
||||
},
|
||||
MuiClockPicker: {
|
||||
styleOverrides: {
|
||||
arrowSwitcher: {
|
||||
'& .MuiIconButton-root:not(.Mui-disabled)': {
|
||||
color: theme.palette.text.secondary,
|
||||
},
|
||||
'& + div': {
|
||||
'& > div': {
|
||||
backgroundColor:
|
||||
theme.palette.mode === 'light' ? theme.palette.grey[50] : theme.palette.background.default,
|
||||
'& ~ .MuiIconButton-root span.MuiTypography-caption': {
|
||||
color: 'inherit',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
MuiMonthPicker: {
|
||||
styleOverrides: {
|
||||
root: {
|
||||
'& > .MuiTypography-root.Mui-selected': {
|
||||
fontSize: '1rem',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export default DateTimePicker;
|
@@ -0,0 +1,104 @@
|
||||
// ** Util Import
|
||||
import { hexToRGBA } from 'src/@core/utils/hex-to-rgba';
|
||||
|
||||
const Dialog = theme => {
|
||||
return {
|
||||
MuiDialog: {
|
||||
styleOverrides: {
|
||||
paper: {
|
||||
boxShadow: theme.shadows[6],
|
||||
'&:not(.MuiDialog-paperFullScreen)': {
|
||||
'@media (max-width:599px)': {
|
||||
margin: theme.spacing(4),
|
||||
width: `calc(100% - ${theme.spacing(8)})`,
|
||||
maxWidth: `calc(100% - ${theme.spacing(8)}) !important`,
|
||||
},
|
||||
},
|
||||
'& > .MuiList-root': {
|
||||
paddingLeft: theme.spacing(1),
|
||||
paddingRight: theme.spacing(1),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
MuiDialogTitle: {
|
||||
styleOverrides: {
|
||||
root: {
|
||||
padding: theme.spacing(5),
|
||||
},
|
||||
},
|
||||
},
|
||||
MuiDialogContent: {
|
||||
styleOverrides: {
|
||||
root: {
|
||||
padding: theme.spacing(5),
|
||||
'& + .MuiDialogContent-root': {
|
||||
paddingTop: 0,
|
||||
},
|
||||
'& + .MuiDialogActions-root': {
|
||||
paddingTop: 0,
|
||||
},
|
||||
|
||||
// Styling for Mobile Date Picker starts
|
||||
'& .PrivatePickersToolbar-root': {
|
||||
padding: theme.spacing(4, 5),
|
||||
color: theme.palette.primary.contrastText,
|
||||
backgroundColor: theme.palette.primary.main,
|
||||
'& .MuiTypography-root': {
|
||||
color: theme.palette.primary.contrastText,
|
||||
},
|
||||
'& span.MuiTypography-overline': {
|
||||
fontSize: '1rem',
|
||||
lineHeight: '24px',
|
||||
letterSpacing: '0.15px',
|
||||
},
|
||||
'& ~ div[class^="css-"] > div[class^="css-"]': {
|
||||
marginTop: theme.spacing(6),
|
||||
marginBottom: theme.spacing(6),
|
||||
'& > div[class^="css-"]': {
|
||||
backgroundColor:
|
||||
theme.palette.mode === 'light' ? theme.palette.grey[50] : theme.palette.background.default,
|
||||
'& ~ .MuiIconButton-root span.MuiTypography-caption': {
|
||||
color: 'inherit',
|
||||
},
|
||||
},
|
||||
},
|
||||
'& .PrivateTimePickerToolbar-hourMinuteLabel': {
|
||||
alignItems: 'center',
|
||||
'& > .MuiButton-root span.MuiTypography-root': {
|
||||
fontWeight: 300,
|
||||
lineHeight: '72px',
|
||||
fontSize: '3.75rem',
|
||||
letterSpacing: '-0.5px',
|
||||
},
|
||||
'& > .MuiTypography-root': {
|
||||
color: hexToRGBA(theme.palette.primary.contrastText, 0.54),
|
||||
'& + .MuiButton-root > span.MuiTypography-root': {
|
||||
color: hexToRGBA(theme.palette.primary.contrastText, 0.54),
|
||||
},
|
||||
},
|
||||
},
|
||||
'& .PrivateTimePickerToolbar-ampmSelection span.MuiTypography-root:not(.Mui-selected)': {
|
||||
color: hexToRGBA(theme.palette.primary.contrastText, 0.54),
|
||||
},
|
||||
},
|
||||
|
||||
// Styling for Mobile Date Picker ends
|
||||
},
|
||||
},
|
||||
},
|
||||
MuiDialogActions: {
|
||||
styleOverrides: {
|
||||
root: {
|
||||
padding: theme.spacing(5),
|
||||
'&.dialog-actions-dense': {
|
||||
padding: theme.spacing(2.5),
|
||||
paddingTop: 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export default Dialog;
|
@@ -0,0 +1,13 @@
|
||||
const Divider = theme => {
|
||||
return {
|
||||
MuiDivider: {
|
||||
styleOverrides: {
|
||||
root: {
|
||||
margin: `${theme.spacing(2)} 0`,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export default Divider;
|
@@ -0,0 +1,85 @@
|
||||
// ** Overrides Imports
|
||||
import MuiCard from './card';
|
||||
import MuiChip from './chip';
|
||||
import MuiLink from './link';
|
||||
import MuiList from './list';
|
||||
import MuiMenu from './menu';
|
||||
import MuiTabs from './tabs';
|
||||
import MuiInput from './input';
|
||||
import MuiPaper from './paper';
|
||||
import MuiTable from './table';
|
||||
import MuiAlerts from './alerts';
|
||||
import MuiButton from './button';
|
||||
import MuiDialog from './dialog';
|
||||
import MuiRating from './rating';
|
||||
import MuiSelect from './select';
|
||||
import MuiAvatar from './avatars';
|
||||
import MuiDivider from './divider';
|
||||
import MuiPopover from './popover';
|
||||
import MuiTooltip from './tooltip';
|
||||
import MuiBackdrop from './backdrop';
|
||||
import MuiSnackbar from './snackbar';
|
||||
import MuiSwitches from './switches';
|
||||
import MuiTimeline from './timeline';
|
||||
import MuiAccordion from './accordion';
|
||||
import MuiPagination from './pagination';
|
||||
import MuiTypography from './typography';
|
||||
import MuiToggleButton from './toggleButton';
|
||||
import MuiDateTimePicker from './dateTimePicker';
|
||||
|
||||
const Overrides = theme => {
|
||||
const chip = MuiChip(theme);
|
||||
const list = MuiList(theme);
|
||||
const menu = MuiMenu(theme);
|
||||
const tabs = MuiTabs(theme);
|
||||
const cards = MuiCard(theme);
|
||||
const input = MuiInput(theme);
|
||||
const tables = MuiTable(theme);
|
||||
const alerts = MuiAlerts(theme);
|
||||
const button = MuiButton(theme);
|
||||
const rating = MuiRating(theme);
|
||||
const avatars = MuiAvatar(theme);
|
||||
const divider = MuiDivider(theme);
|
||||
const dialog = MuiDialog(theme);
|
||||
const popover = MuiPopover(theme);
|
||||
const tooltip = MuiTooltip(theme);
|
||||
const backdrop = MuiBackdrop(theme);
|
||||
const snackbar = MuiSnackbar(theme);
|
||||
const switches = MuiSwitches(theme);
|
||||
const timeline = MuiTimeline(theme);
|
||||
const accordion = MuiAccordion(theme);
|
||||
const pagination = MuiPagination(theme);
|
||||
const dateTimePicker = MuiDateTimePicker(theme);
|
||||
|
||||
return Object.assign(
|
||||
chip,
|
||||
list,
|
||||
menu,
|
||||
tabs,
|
||||
cards,
|
||||
input,
|
||||
alerts,
|
||||
button,
|
||||
dialog,
|
||||
rating,
|
||||
tables,
|
||||
avatars,
|
||||
divider,
|
||||
MuiLink,
|
||||
popover,
|
||||
tooltip,
|
||||
backdrop,
|
||||
MuiPaper,
|
||||
snackbar,
|
||||
switches,
|
||||
timeline,
|
||||
accordion,
|
||||
MuiSelect,
|
||||
pagination,
|
||||
MuiTypography,
|
||||
dateTimePicker,
|
||||
MuiToggleButton,
|
||||
);
|
||||
};
|
||||
|
||||
export default Overrides;
|
@@ -0,0 +1,62 @@
|
||||
const input = theme => {
|
||||
return {
|
||||
MuiInputLabel: {
|
||||
styleOverrides: {
|
||||
root: {
|
||||
color: theme.palette.text.secondary,
|
||||
},
|
||||
},
|
||||
},
|
||||
MuiInput: {
|
||||
styleOverrides: {
|
||||
root: {
|
||||
'&:before': {
|
||||
borderBottom: `1px solid rgba(${theme.palette.customColors.main}, 0.22)`,
|
||||
},
|
||||
'&:hover:not(.Mui-disabled):before': {
|
||||
borderBottom: `1px solid rgba(${theme.palette.customColors.main}, 0.32)`,
|
||||
},
|
||||
'&.Mui-disabled:before': {
|
||||
borderBottom: `1px solid ${theme.palette.text.disabled}`,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
MuiFilledInput: {
|
||||
styleOverrides: {
|
||||
root: {
|
||||
backgroundColor: `rgba(${theme.palette.customColors.main}, 0.04)`,
|
||||
'&:hover:not(.Mui-disabled)': {
|
||||
backgroundColor: `rgba(${theme.palette.customColors.main}, 0.08)`,
|
||||
},
|
||||
'&:before': {
|
||||
borderBottom: `1px solid rgba(${theme.palette.customColors.main}, 0.22)`,
|
||||
},
|
||||
'&:hover:not(.Mui-disabled):before': {
|
||||
borderBottom: `1px solid rgba(${theme.palette.customColors.main}, 0.32)`,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
MuiOutlinedInput: {
|
||||
styleOverrides: {
|
||||
root: {
|
||||
'&:hover:not(.Mui-focused) .MuiOutlinedInput-notchedOutline': {
|
||||
borderColor: `rgba(${theme.palette.customColors.main}, 0.32)`,
|
||||
},
|
||||
'&:hover.Mui-error .MuiOutlinedInput-notchedOutline': {
|
||||
borderColor: theme.palette.error.main,
|
||||
},
|
||||
'& .MuiOutlinedInput-notchedOutline': {
|
||||
borderColor: `rgba(${theme.palette.customColors.main}, 0.22)`,
|
||||
},
|
||||
'&.Mui-disabled .MuiOutlinedInput-notchedOutline': {
|
||||
borderColor: theme.palette.text.disabled,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export default input;
|
@@ -0,0 +1,9 @@
|
||||
export default {
|
||||
MuiLink: {
|
||||
styleOverrides: {
|
||||
root: {
|
||||
textDecoration: 'none',
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
@@ -0,0 +1,41 @@
|
||||
const List = theme => {
|
||||
return {
|
||||
MuiListItemIcon: {
|
||||
styleOverrides: {
|
||||
root: {
|
||||
minWidth: 0,
|
||||
marginRight: theme.spacing(2.25),
|
||||
color: theme.palette.text.secondary,
|
||||
},
|
||||
},
|
||||
},
|
||||
MuiListItemAvatar: {
|
||||
styleOverrides: {
|
||||
root: {
|
||||
minWidth: 0,
|
||||
marginRight: theme.spacing(4),
|
||||
},
|
||||
},
|
||||
},
|
||||
MuiListItemText: {
|
||||
styleOverrides: {
|
||||
dense: {
|
||||
'& .MuiListItemText-primary': {
|
||||
color: theme.palette.text.primary,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
MuiListSubheader: {
|
||||
styleOverrides: {
|
||||
root: {
|
||||
fontWeight: 600,
|
||||
textTransform: 'uppercase',
|
||||
color: theme.palette.text.primary,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export default List;
|
@@ -0,0 +1,16 @@
|
||||
const Menu = theme => {
|
||||
return {
|
||||
MuiMenu: {
|
||||
styleOverrides: {
|
||||
root: {
|
||||
'& .MuiMenu-paper': {
|
||||
borderRadius: 5,
|
||||
boxShadow: theme.palette.mode === 'light' ? theme.shadows[8] : theme.shadows[9],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export default Menu;
|
@@ -0,0 +1,38 @@
|
||||
// ** Util Import
|
||||
import { hexToRGBA } from 'src/@core/utils/hex-to-rgba';
|
||||
|
||||
const Pagination = theme => {
|
||||
return {
|
||||
MuiPaginationItem: {
|
||||
styleOverrides: {
|
||||
root: {
|
||||
'&.Mui-selected:not(.Mui-disabled):not(.MuiPaginationItem-textPrimary):not(.MuiPaginationItem-textSecondary):hover':
|
||||
{
|
||||
backgroundColor: `rgba(${theme.palette.customColors.main}, 0.12)`,
|
||||
},
|
||||
},
|
||||
outlined: {
|
||||
borderColor: `rgba(${theme.palette.customColors.main}, 0.22)`,
|
||||
},
|
||||
outlinedPrimary: {
|
||||
'&.Mui-selected': {
|
||||
backgroundColor: hexToRGBA(theme.palette.primary.main, 0.12),
|
||||
'&:hover': {
|
||||
backgroundColor: `${hexToRGBA(theme.palette.primary.main, 0.2)} !important`,
|
||||
},
|
||||
},
|
||||
},
|
||||
outlinedSecondary: {
|
||||
'&.Mui-selected': {
|
||||
backgroundColor: hexToRGBA(theme.palette.secondary.main, 0.12),
|
||||
'&:hover': {
|
||||
backgroundColor: `${hexToRGBA(theme.palette.secondary.main, 0.2)} !important`,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export default Pagination;
|
@@ -0,0 +1,9 @@
|
||||
export default {
|
||||
MuiPaper: {
|
||||
styleOverrides: {
|
||||
root: {
|
||||
backgroundImage: 'none',
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
@@ -0,0 +1,15 @@
|
||||
const Popover = theme => {
|
||||
return {
|
||||
MuiPopover: {
|
||||
styleOverrides: {
|
||||
root: {
|
||||
'& .MuiPopover-paper': {
|
||||
boxShadow: theme.shadows[6],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export default Popover;
|
@@ -0,0 +1,13 @@
|
||||
const Rating = theme => {
|
||||
return {
|
||||
MuiRating: {
|
||||
styleOverrides: {
|
||||
root: {
|
||||
color: theme.palette.warning.main,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export default Rating;
|
@@ -0,0 +1,12 @@
|
||||
export default {
|
||||
MuiSelect: {
|
||||
styleOverrides: {
|
||||
select: {
|
||||
minWidth: '6rem !important',
|
||||
'&.MuiTablePagination-select': {
|
||||
minWidth: '1rem !important',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
@@ -0,0 +1,13 @@
|
||||
const Snackbar = theme => {
|
||||
return {
|
||||
MuiSnackbarContent: {
|
||||
styleOverrides: {
|
||||
root: {
|
||||
backgroundColor: theme.palette.mode === 'light' ? theme.palette.grey[900] : theme.palette.grey[100],
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export default Snackbar;
|
@@ -0,0 +1,15 @@
|
||||
const Switch = theme => {
|
||||
return {
|
||||
MuiSwitch: {
|
||||
styleOverrides: {
|
||||
root: {
|
||||
'& .MuiSwitch-track': {
|
||||
backgroundColor: `rgb(${theme.palette.customColors.main})`,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export default Switch;
|
@@ -0,0 +1,66 @@
|
||||
const Table = theme => {
|
||||
return {
|
||||
MuiTableContainer: {
|
||||
styleOverrides: {
|
||||
root: {
|
||||
boxShadow: theme.shadows[0],
|
||||
borderTopColor: theme.palette.divider,
|
||||
},
|
||||
},
|
||||
},
|
||||
MuiTableHead: {
|
||||
styleOverrides: {
|
||||
root: {
|
||||
textTransform: 'uppercase',
|
||||
'& .MuiTableCell-head': {
|
||||
fontSize: '0.75rem',
|
||||
fontWeight: 600,
|
||||
letterSpacing: '0.13px',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
MuiTableBody: {
|
||||
styleOverrides: {
|
||||
root: {
|
||||
'& .MuiTableCell-body': {
|
||||
letterSpacing: '0.25px',
|
||||
color: theme.palette.text.secondary,
|
||||
'&:not(.MuiTableCell-sizeSmall):not(.MuiTableCell-paddingCheckbox):not(.MuiTableCell-paddingNone)': {
|
||||
paddingTop: theme.spacing(3.5),
|
||||
paddingBottom: theme.spacing(3.5),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
MuiTableRow: {
|
||||
styleOverrides: {
|
||||
root: {
|
||||
'& .MuiTableCell-head:first-child, & .MuiTableCell-root:first-child ': {
|
||||
paddingLeft: theme.spacing(5),
|
||||
},
|
||||
'& .MuiTableCell-head:last-child, & .MuiTableCell-root:last-child': {
|
||||
paddingRight: theme.spacing(5),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
MuiTableCell: {
|
||||
styleOverrides: {
|
||||
root: {
|
||||
borderBottom: `1px solid ${theme.palette.divider}`,
|
||||
'& .MuiButton-root': {
|
||||
textTransform: 'uppercase',
|
||||
color: theme.palette.text.secondary,
|
||||
},
|
||||
},
|
||||
stickyHeader: {
|
||||
backgroundColor: theme.palette.customColors.tableHeaderBg,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export default Table;
|
@@ -0,0 +1,27 @@
|
||||
const Tabs = theme => {
|
||||
return {
|
||||
MuiTabs: {
|
||||
styleOverrides: {
|
||||
vertical: {
|
||||
minWidth: 130,
|
||||
marginRight: theme.spacing(4),
|
||||
borderRight: `1px solid ${theme.palette.divider}`,
|
||||
'& .MuiTab-root': {
|
||||
minWidth: 130,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
MuiTab: {
|
||||
styleOverrides: {
|
||||
textColorSecondary: {
|
||||
'&.Mui-selected': {
|
||||
color: theme.palette.text.secondary,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export default Tabs;
|
@@ -0,0 +1,80 @@
|
||||
// ** Util Import
|
||||
import { hexToRGBA } from 'src/@core/utils/hex-to-rgba';
|
||||
|
||||
const Timeline = theme => {
|
||||
return {
|
||||
MuiTimelineItem: {
|
||||
styleOverrides: {
|
||||
root: {
|
||||
'&:not(:last-of-type)': {
|
||||
'& .MuiTimelineContent-root': {
|
||||
marginBottom: theme.spacing(4),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
MuiTimelineConnector: {
|
||||
styleOverrides: {
|
||||
root: {
|
||||
backgroundColor: theme.palette.divider,
|
||||
},
|
||||
},
|
||||
},
|
||||
MuiTimelineContent: {
|
||||
styleOverrides: {
|
||||
root: {
|
||||
marginTop: theme.spacing(0.5),
|
||||
},
|
||||
},
|
||||
},
|
||||
MuiTimelineDot: {
|
||||
styleOverrides: {
|
||||
filledPrimary: {
|
||||
boxShadow: `0 0 0 3px ${hexToRGBA(theme.palette.primary.main, 0.12)}`,
|
||||
},
|
||||
filledSecondary: {
|
||||
boxShadow: `0 0 0 3px ${hexToRGBA(theme.palette.secondary.main, 0.12)}`,
|
||||
},
|
||||
filledSuccess: {
|
||||
boxShadow: `0 0 0 3px ${hexToRGBA(theme.palette.success.main, 0.12)}`,
|
||||
},
|
||||
filledError: {
|
||||
boxShadow: `0 0 0 3px ${hexToRGBA(theme.palette.error.main, 0.12)}`,
|
||||
},
|
||||
filledWarning: {
|
||||
boxShadow: `0 0 0 3px ${hexToRGBA(theme.palette.warning.main, 0.12)}`,
|
||||
},
|
||||
filledInfo: {
|
||||
boxShadow: `0 0 0 3px ${hexToRGBA(theme.palette.info.main, 0.12)}`,
|
||||
},
|
||||
filledGrey: {
|
||||
boxShadow: `0 0 0 3px ${hexToRGBA(theme.palette.grey[400], 0.12)}`,
|
||||
},
|
||||
outlinedPrimary: {
|
||||
'& svg': { color: theme.palette.primary.main },
|
||||
},
|
||||
outlinedSecondary: {
|
||||
'& svg': { color: theme.palette.secondary.main },
|
||||
},
|
||||
outlinedSuccess: {
|
||||
'& svg': { color: theme.palette.success.main },
|
||||
},
|
||||
outlinedError: {
|
||||
'& svg': { color: theme.palette.error.main },
|
||||
},
|
||||
outlinedWarning: {
|
||||
'& svg': { color: theme.palette.warning.main },
|
||||
},
|
||||
outlinedInfo: {
|
||||
'& svg': { color: theme.palette.info.main },
|
||||
},
|
||||
outlinedGrey: {
|
||||
'& svg': { color: theme.palette.grey[500] },
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export default Timeline;
|
@@ -0,0 +1,16 @@
|
||||
export default {
|
||||
MuiToggleButtonGroup: {
|
||||
styleOverrides: {
|
||||
root: {
|
||||
borderRadius: 4,
|
||||
},
|
||||
},
|
||||
},
|
||||
MuiToggleButton: {
|
||||
styleOverrides: {
|
||||
root: {
|
||||
borderRadius: 4,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
@@ -0,0 +1,25 @@
|
||||
// ** Util Import
|
||||
import { hexToRGBA } from 'src/@core/utils/hex-to-rgba';
|
||||
|
||||
const Tooltip = theme => {
|
||||
return {
|
||||
MuiTooltip: {
|
||||
styleOverrides: {
|
||||
tooltip: {
|
||||
backgroundColor:
|
||||
theme.palette.mode === 'light'
|
||||
? hexToRGBA(theme.palette.grey[900], 0.9)
|
||||
: hexToRGBA(theme.palette.grey[700], 0.9),
|
||||
},
|
||||
arrow: {
|
||||
color:
|
||||
theme.palette.mode === 'light'
|
||||
? hexToRGBA(theme.palette.grey[900], 0.9)
|
||||
: hexToRGBA(theme.palette.grey[700], 0.9),
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export default Tooltip;
|
@@ -0,0 +1,13 @@
|
||||
const Typography = theme => {
|
||||
return {
|
||||
MuiTypography: {
|
||||
styleOverrides: {
|
||||
gutterBottom: {
|
||||
marginBottom: theme.spacing(2),
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export default Typography;
|
@@ -0,0 +1,107 @@
|
||||
const DefaultPalette = (mode, themeColor) => {
|
||||
// ** Vars
|
||||
const lightColor = '58, 53, 65';
|
||||
const darkColor = '231, 227, 252';
|
||||
const mainColor = mode === 'light' ? lightColor : darkColor;
|
||||
|
||||
const primaryGradient = () => {
|
||||
if (themeColor === 'primary') {
|
||||
return 'rgba(12, 45, 87,0.7)';
|
||||
} else if (themeColor === 'secondary') {
|
||||
return '#9C9FA4';
|
||||
} else if (themeColor === 'success') {
|
||||
return '#93DD5C';
|
||||
} else if (themeColor === 'error') {
|
||||
return '#FF8C90';
|
||||
} else if (themeColor === 'warning') {
|
||||
return '#FFCF5C';
|
||||
} else {
|
||||
return '#6ACDFF';
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
customColors: {
|
||||
main: mainColor,
|
||||
primaryGradient: primaryGradient(),
|
||||
tableHeaderBg: mode === 'light' ? '#F9FAFC' : '#3D3759',
|
||||
},
|
||||
common: {
|
||||
black: '#000',
|
||||
white: '#FFF',
|
||||
},
|
||||
mode: mode,
|
||||
primary: {
|
||||
light: 'rgba(12, 45, 87,0.2)',
|
||||
main: 'rgba(12, 45, 87,0.7)',
|
||||
dark: 'rgba(12, 45, 87,1)',
|
||||
contrastText: '#FFF',
|
||||
},
|
||||
secondary: {
|
||||
light: '#9C9FA4',
|
||||
main: '#8A8D93',
|
||||
dark: '#777B82',
|
||||
contrastText: '#FFF',
|
||||
},
|
||||
success: {
|
||||
light: '#6AD01F',
|
||||
main: '#56CA00',
|
||||
dark: '#4CB200',
|
||||
contrastText: '#FFF',
|
||||
},
|
||||
error: {
|
||||
light: '#FF6166',
|
||||
main: '#FF4C51',
|
||||
dark: '#E04347',
|
||||
contrastText: '#FFF',
|
||||
},
|
||||
warning: {
|
||||
light: '#FFCA64',
|
||||
main: '#FFB400',
|
||||
dark: '#E09E00',
|
||||
contrastText: '#FFF',
|
||||
},
|
||||
info: {
|
||||
light: '#32BAFF',
|
||||
main: '#16B1FF',
|
||||
dark: '#139CE0',
|
||||
contrastText: '#FFF',
|
||||
},
|
||||
grey: {
|
||||
50: '#FAFAFA',
|
||||
100: '#F5F5F5',
|
||||
200: '#EEEEEE',
|
||||
300: '#E0E0E0',
|
||||
400: '#BDBDBD',
|
||||
500: '#9E9E9E',
|
||||
600: '#757575',
|
||||
700: '#616161',
|
||||
800: '#424242',
|
||||
900: '#212121',
|
||||
A100: '#D5D5D5',
|
||||
A200: '#AAAAAA',
|
||||
A400: '#616161',
|
||||
A700: '#303030',
|
||||
},
|
||||
text: {
|
||||
primary: `rgba(${mainColor}, 0.87)`,
|
||||
secondary: `rgba(${mainColor}, 0.68)`,
|
||||
disabled: `rgba(${mainColor}, 0.38)`,
|
||||
},
|
||||
divider: `rgba(${mainColor}, 0.12)`,
|
||||
background: {
|
||||
paper: mode === 'light' ? '#FFF' : '#312D4B',
|
||||
default: mode === 'light' ? '#F4F5FA' : '#28243D',
|
||||
},
|
||||
action: {
|
||||
active: `rgba(${mainColor}, 0.54)`,
|
||||
hover: `rgba(${mainColor}, 0.04)`,
|
||||
selected: `rgba(${mainColor}, 0.08)`,
|
||||
disabled: `rgba(${mainColor}, 0.3)`,
|
||||
disabledBackground: `rgba(${mainColor}, 0.18)`,
|
||||
focus: `rgba(${mainColor}, 0.12)`,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export default DefaultPalette;
|
@@ -0,0 +1,61 @@
|
||||
const Shadows = mode => {
|
||||
if (mode === 'light') {
|
||||
return [
|
||||
'none',
|
||||
'0px 2px 1px -1px rgba(58, 53, 65, 0.2), 0px 1px 1px 0px rgba(58, 53, 65, 0.14), 0px 1px 3px 0px rgba(58, 53, 65, 0.12)',
|
||||
'0px 3px 1px -2px rgba(58, 53, 65, 0.2), 0px 2px 2px 0px rgba(58, 53, 65, 0.14), 0px 1px 5px 0px rgba(58, 53, 65, 0.12)',
|
||||
'0px 4px 8px -4px rgba(58, 53, 65, 0.42)',
|
||||
'0px 6px 18px -8px rgba(58, 53, 65, 0.56)',
|
||||
'0px 3px 5px -1px rgba(58, 53, 65, 0.2), 0px 5px 8px 0px rgba(58, 53, 65, 0.14), 0px 1px 14px 0px rgba(58, 53, 65, 0.12)',
|
||||
'0px 2px 10px 0px rgba(58, 53, 65, 0.1)',
|
||||
'0px 4px 5px -2px rgba(58, 53, 65, 0.2), 0px 7px 10px 1px rgba(58, 53, 65, 0.14), 0px 2px 16px 1px rgba(58, 53, 65, 0.12)',
|
||||
'0px 5px 5px -3px rgba(58, 53, 65, 0.2), 0px 8px 10px 1px rgba(58, 53, 65, 0.14), 0px 3px 14px 2px rgba(58, 53, 65, 0.12)',
|
||||
'0px 5px 6px -3px rgba(58, 53, 65, 0.2), 0px 9px 12px 1px rgba(58, 53, 65, 0.14), 0px 3px 16px 2px rgba(58, 53, 65, 0.12)',
|
||||
'0px 6px 6px -3px rgba(58, 53, 65, 0.2), 0px 10px 14px 1px rgba(58, 53, 65, 0.14), 0px 4px 18px 3px rgba(58, 53, 65, 0.12)',
|
||||
'0px 6px 7px -4px rgba(58, 53, 65, 0.2), 0px 11px 15px 1px rgba(58, 53, 65, 0.14), 0px 4px 20px 3px rgba(58, 53, 65, 0.12)',
|
||||
'0px 7px 8px -4px rgba(58, 53, 65, 0.2), 0px 12px 17px 2px rgba(58, 53, 65, 0.14), 0px 5px 22px 4px rgba(58, 53, 65, 0.12)',
|
||||
'0px 7px 8px -4px rgba(58, 53, 65, 0.2), 0px 13px 19px 2px rgba(58, 53, 65, 0.14), 0px 5px 24px 4px rgba(58, 53, 65, 0.12)',
|
||||
'0px 7px 9px -4px rgba(58, 53, 65, 0.2), 0px 14px 21px 2px rgba(58, 53, 65, 0.14), 0px 5px 26px 4px rgba(58, 53, 65, 0.12)',
|
||||
'0px 8px 9px -5px rgba(58, 53, 65, 0.2), 0px 15px 22px 2px rgba(58, 53, 65, 0.14), 0px 6px 28px 5px rgba(58, 53, 65, 0.12)',
|
||||
'0px 8px 10px -5px rgba(58, 53, 65, 0.2), 0px 16px 24px 2px rgba(58, 53, 65, 0.14), 0px 6px 30px 5px rgba(58, 53, 65, 0.12)',
|
||||
'0px 8px 11px -5px rgba(58, 53, 65, 0.2), 0px 17px 26px 2px rgba(58, 53, 65, 0.14), 0px 6px 32px 5px rgba(58, 53, 65, 0.12)',
|
||||
'0px 9px 11px -5px rgba(58, 53, 65, 0.2), 0px 18px 28px 2px rgba(58, 53, 65, 0.14), 0px 7px 34px 6px rgba(58, 53, 65, 0.12)',
|
||||
'0px 9px 12px -6px rgba(58, 53, 65, 0.2), 0px 19px 29px 2px rgba(58, 53, 65, 0.14), 0px 7px 36px 6px rgba(58, 53, 65, 0.12)',
|
||||
'0px 10px 13px -6px rgba(58, 53, 65, 0.2), 0px 20px 31px 3px rgba(58, 53, 65, 0.14), 0px 8px 38px 7px rgba(58, 53, 65, 0.12)',
|
||||
'0px 10px 13px -6px rgba(58, 53, 65, 0.2), 0px 21px 33px 3px rgba(58, 53, 65, 0.14), 0px 8px 40px 7px rgba(58, 53, 65, 0.12)',
|
||||
'0px 10px 14px -6px rgba(58, 53, 65, 0.2), 0px 22px 35px 3px rgba(58, 53, 65, 0.14), 0px 8px 42px 7px rgba(58, 53, 65, 0.12)',
|
||||
'0px 11px 14px -7px rgba(58, 53, 65, 0.2), 0px 23px 36px 3px rgba(58, 53, 65, 0.14), 0px 9px 44px 8px rgba(58, 53, 65, 0.12)',
|
||||
'0px 11px 15px -7px rgba(58, 53, 65, 0.2), 0px 24px 38px 3px rgba(58, 53, 65, 0.14), 0px 9px 46px 8px rgba(58, 53, 65, 0.12)',
|
||||
];
|
||||
} else {
|
||||
return [
|
||||
'none',
|
||||
'0px 2px 1px -1px rgba(19, 17, 32, 0.2), 0px 1px 1px 0px rgba(19, 17, 32, 0.14), 0px 1px 3px 0px rgba(19, 17, 32, 0.12)',
|
||||
'0px 3px 1px -2px rgba(19, 17, 32, 0.2), 0px 2px 2px 0px rgba(19, 17, 32, 0.14), 0px 1px 5px 0px rgba(19, 17, 32, 0.12)',
|
||||
'0px 4px 8px -4px rgba(19, 17, 32, 0.42)',
|
||||
'0px 6px 18px -8px rgba(19, 17, 32, 0.56)',
|
||||
'0px 3px 5px -1px rgba(19, 17, 32, 0.2), 0px 5px 8px rgba(19, 17, 32, 0.14), 0px 1px 14px rgba(19, 17, 32, 0.12)',
|
||||
'0px 2px 10px 0px rgba(19, 17, 32, 0.1)',
|
||||
'0px 4px 5px -2px rgba(19, 17, 32, 0.2), 0px 7px 10px 1px rgba(19, 17, 32, 0.14), 0px 2px 16px 1px rgba(19, 17, 32, 0.12)',
|
||||
'0px 5px 5px -3px rgba(19, 17, 32, 0.2), 0px 8px 10px 1px rgba(19, 17, 32, 0.14), 0px 3px 14px 2px rgba(19, 17, 32, 0.12)',
|
||||
'0px 5px 6px -3px rgba(19, 17, 32, 0.2), 0px 9px 12px 1px rgba(19, 17, 32, 0.14), 0px 3px 16px 2px rgba(19, 17, 32, 0.12)',
|
||||
'0px 6px 6px -3px rgba(19, 17, 32, 0.2), 0px 10px 14px 1px rgba(19, 17, 32, 0.14), 0px 4px 18px 3px rgba(19, 17, 32, 0.12)',
|
||||
'0px 6px 7px -4px rgba(19, 17, 32, 0.2), 0px 11px 15px 1px rgba(19, 17, 32, 0.14), 0px 4px 20px 3px rgba(19, 17, 32, 0.12)',
|
||||
'0px 7px 8px -4px rgba(19, 17, 32, 0.2), 0px 12px 17px 2px rgba(19, 17, 32, 0.14), 0px 5px 22px 4px rgba(19, 17, 32, 0.12)',
|
||||
'0px 7px 8px -4px rgba(19, 17, 32, 0.2), 0px 13px 19px 2px rgba(19, 17, 32, 0.14), 0px 5px 24px 4px rgba(19, 17, 32, 0.12)',
|
||||
'0px 7px 9px -4px rgba(19, 17, 32, 0.2), 0px 14px 21px 2px rgba(19, 17, 32, 0.14), 0px 5px 26px 4px rgba(19, 17, 32, 0.12)',
|
||||
'0px 8px 9px -5px rgba(19, 17, 32, 0.2), 0px 15px 22px 2px rgba(19, 17, 32, 0.14), 0px 6px 28px 5px rgba(19, 17, 32, 0.12)',
|
||||
'0px 8px 10px -5px rgba(19, 17, 32, 0.2), 0px 16px 24px 2px rgba(19, 17, 32, 0.14), 0px 6px 30px 5px rgba(19, 17, 32, 0.12)',
|
||||
'0px 8px 11px -5px rgba(19, 17, 32, 0.2), 0px 17px 26px 2px rgba(19, 17, 32, 0.14), 0px 6px 32px 5px rgba(19, 17, 32, 0.12)',
|
||||
'0px 9px 11px -5px rgba(19, 17, 32, 0.2), 0px 18px 28px 2px rgba(19, 17, 32, 0.14), 0px 7px 34px 6px rgba(19, 17, 32, 0.12)',
|
||||
'0px 9px 12px -6px rgba(19, 17, 32, 0.2), 0px 19px 29px 2px rgba(19, 17, 32, 0.14), 0px 7px 36px 6px rgba(19, 17, 32, 0.12)',
|
||||
'0px 10px 13px -6px rgba(19, 17, 32, 0.2), 0px 20px 31px 3px rgba(19, 17, 32, 0.14), 0px 8px 38px 7px rgba(19, 17, 32, 0.12)',
|
||||
'0px 10px 13px -6px rgba(19, 17, 32, 0.2), 0px 21px 33px 3px rgba(19, 17, 32, 0.14), 0px 8px 40px 7px rgba(19, 17, 32, 0.12)',
|
||||
'0px 10px 14px -6px rgba(19, 17, 32, 0.2), 0px 22px 35px 3px rgba(19, 17, 32, 0.14), 0px 8px 42px 7px rgba(19, 17, 32, 0.12)',
|
||||
'0px 11px 14px -7px rgba(19, 17, 32, 0.2), 0px 23px 36px 3px rgba(19, 17, 32, 0.14), 0px 9px 44px 8px rgba(19, 17, 32, 0.12)',
|
||||
'0px 11px 15px -7px rgba(19, 17, 32, 0.2), 0px 24px 38px 3px rgba(19, 17, 32, 0.14), 0px 9px 46px 8px rgba(19, 17, 32, 0.12)',
|
||||
];
|
||||
}
|
||||
};
|
||||
|
||||
export default Shadows;
|
@@ -0,0 +1,3 @@
|
||||
export default {
|
||||
spacing: factor => `${0.25 * factor}rem`,
|
||||
};
|
@@ -0,0 +1,3 @@
|
||||
export default {
|
||||
spacing: factor => `${0.25 * factor}rem`
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user