+ Your Next Favorite Tech
is Just a Click Away
+
+ + Browse the latest smartphones, tablets, and accessories. Fast delivery and secure payments guaranteed. +
+ +diff --git a/backend/src/db/db.config.js b/backend/src/db/db.config.js
index 46565e4..d87d268 100644
--- a/backend/src/db/db.config.js
+++ b/backend/src/db/db.config.js
@@ -1,5 +1,3 @@
-
-
module.exports = {
production: {
dialect: 'postgres',
@@ -12,11 +10,12 @@ module.exports = {
seederStorage: 'sequelize',
},
development: {
- username: 'postgres',
dialect: 'postgres',
- password: '',
- database: 'db_mobile_commerce_store',
+ username: process.env.DB_USER || 'postgres',
+ password: process.env.DB_PASS || '',
+ database: process.env.DB_NAME || 'db_mobile_commerce_store',
host: process.env.DB_HOST || 'localhost',
+ port: process.env.DB_PORT || 5432,
logging: console.log,
seederStorage: 'sequelize',
},
@@ -30,4 +29,4 @@ module.exports = {
logging: console.log,
seederStorage: 'sequelize',
}
-};
+};
\ No newline at end of file
diff --git a/backend/src/db/migrations/1770657891319.js b/backend/src/db/migrations/1770657891319.js
new file mode 100644
index 0000000..bc06082
--- /dev/null
+++ b/backend/src/db/migrations/1770657891319.js
@@ -0,0 +1,48 @@
+module.exports = {
+ async up(queryInterface, Sequelize) {
+ const [roles] = await queryInterface.sequelize.query(
+ `SELECT id FROM "roles" WHERE name = 'Public' LIMIT 1;`
+ );
+ const [readProductsPerm] = await queryInterface.sequelize.query(
+ `SELECT id FROM "permissions" WHERE name = 'READ_PRODUCTS' LIMIT 1;`
+ );
+ const [readCategoriesPerm] = await queryInterface.sequelize.query(
+ `SELECT id FROM "permissions" WHERE name = 'READ_CATEGORIES' LIMIT 1;`
+ );
+
+ if (roles.length && readProductsPerm.length) {
+ const [existing] = await queryInterface.sequelize.query(
+ `SELECT * FROM "rolesPermissionsPermissions" WHERE "roles_permissionsId" = '${roles[0].id}' AND "permissionId" = '${readProductsPerm[0].id}';`
+ );
+ if (!existing.length) {
+ await queryInterface.bulkInsert('rolesPermissionsPermissions', [
+ {
+ createdAt: new Date(),
+ updatedAt: new Date(),
+ roles_permissionsId: roles[0].id,
+ permissionId: readProductsPerm[0].id,
+ },
+ ]);
+ }
+ }
+
+ if (roles.length && readCategoriesPerm.length) {
+ const [existing] = await queryInterface.sequelize.query(
+ `SELECT * FROM "rolesPermissionsPermissions" WHERE "roles_permissionsId" = '${roles[0].id}' AND "permissionId" = '${readCategoriesPerm[0].id}';`
+ );
+ if (!existing.length) {
+ await queryInterface.bulkInsert('rolesPermissionsPermissions', [
+ {
+ createdAt: new Date(),
+ updatedAt: new Date(),
+ roles_permissionsId: roles[0].id,
+ permissionId: readCategoriesPerm[0].id,
+ },
+ ]);
+ }
+ }
+ },
+
+ async down(queryInterface, Sequelize) {
+ }
+};
\ No newline at end of file
diff --git a/backend/src/index.js b/backend/src/index.js
index 730ce1b..c1eb115 100644
--- a/backend/src/index.js
+++ b/backend/src/index.js
@@ -131,9 +131,9 @@ app.use('/api/addresses', passport.authenticate('jwt', {session: false}), addres
app.use('/api/brands', passport.authenticate('jwt', {session: false}), brandsRoutes);
-app.use('/api/categories', passport.authenticate('jwt', {session: false}), categoriesRoutes);
+app.use('/api/categories', categoriesRoutes);
-app.use('/api/products', passport.authenticate('jwt', {session: false}), productsRoutes);
+app.use('/api/products', productsRoutes);
app.use('/api/product_variants', passport.authenticate('jwt', {session: false}), product_variantsRoutes);
diff --git a/frontend/src/components/WebPageComponents/Footer.tsx b/frontend/src/components/WebPageComponents/Footer.tsx
new file mode 100644
index 0000000..65b81d3
--- /dev/null
+++ b/frontend/src/components/WebPageComponents/Footer.tsx
@@ -0,0 +1,36 @@
+
+import React from 'react';
+import Link from 'next/link';
+
+export default function WebSiteFooter({ projectName }: { projectName: string }) {
+ return (
+
+ );
+}
diff --git a/frontend/src/components/WebPageComponents/Header.tsx b/frontend/src/components/WebPageComponents/Header.tsx
new file mode 100644
index 0000000..c8de219
--- /dev/null
+++ b/frontend/src/components/WebPageComponents/Header.tsx
@@ -0,0 +1,44 @@
+
+import React, { useState } from 'react';
+import Link from 'next/link';
+import { mdiAccount, mdiCart, mdiMenu, mdiClose } from '@mdi/js';
+import BaseIcon from '../BaseIcon';
+
+export default function WebSiteHeader({ projectName }: { projectName: string }) {
+ const [isMenuOpen, setIsMenuOpen] = useState(false);
+
+ return (
+
This is a React.js/Node.js app generated by the Flatlogic Web App Generator
-For guides and documentation please check - your local README.md and the Flatlogic documentation
++ Browse the latest smartphones, tablets, and accessories. Fast delivery and secure payments guaranteed. +
+ +© 2026 {title}. All rights reserved
- - Privacy Policy - -+ {product.short_description || 'High-quality product for your everyday needs.'} +
+No products found for this category.
+We only sell products from trusted brands with high customer ratings.
+Get your tech delivered to your doorstep within 24-48 hours.
+All transactions are encrypted and processed through secure gateways.
+