inital commit
This commit is contained in:
parent
33eb86d6ed
commit
b870378fae
9
.cursor/rules/react.mdc
Normal file
9
.cursor/rules/react.mdc
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
---
|
||||||
|
description:
|
||||||
|
globs:
|
||||||
|
alwaysApply: true
|
||||||
|
---
|
||||||
|
|
||||||
|
# React components
|
||||||
|
1. You will always provide a maintainable folder structure when adding or updating react components.
|
||||||
|
2. You will reuse common components
|
||||||
@ -1,4 +1,7 @@
|
|||||||
You are an expert React and PHP Symfony developer.
|
You are an expert React and PHP Symfony developer.
|
||||||
You will build very clean and abstract code to provide a clean and extendable codebase.
|
You will build very clean and abstract code to provide a clean and extendable codebase.
|
||||||
You are using PHP 8.4 with the latest symfony in the backend directory.
|
You are using PHP 8.4 with the latest symfony in the backend directory.
|
||||||
You are using the latest React version in the frontend directory
|
You are using the latest React version in the frontend directory
|
||||||
|
|
||||||
|
You will never use react native components
|
||||||
|
You will rarely install new packages
|
||||||
3
.gitignore
vendored
3
.gitignore
vendored
@ -1 +1,2 @@
|
|||||||
var
|
var
|
||||||
|
node_modules
|
||||||
|
|||||||
@ -5,7 +5,7 @@ set -e
|
|||||||
service php8.4-fpm start
|
service php8.4-fpm start
|
||||||
|
|
||||||
# Change to frontend directory and start npm in background
|
# Change to frontend directory and start npm in background
|
||||||
cd /var/www/html/frontend && npm start &
|
cd /var/www/html/frontend && npm run start &
|
||||||
|
|
||||||
# Start Nginx in foreground to keep container running
|
# Start Nginx in foreground to keep container running
|
||||||
exec nginx -g 'daemon off;'
|
exec nginx -g 'daemon off;'
|
||||||
75
frontend/package-lock.json
generated
75
frontend/package-lock.json
generated
@ -6,6 +6,11 @@
|
|||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@fortawesome/fontawesome-svg-core": "^6.7.2",
|
||||||
|
"@fortawesome/free-brands-svg-icons": "^6.7.2",
|
||||||
|
"@fortawesome/free-regular-svg-icons": "^6.7.2",
|
||||||
|
"@fortawesome/free-solid-svg-icons": "^6.7.2",
|
||||||
|
"@fortawesome/react-fontawesome": "^0.2.2",
|
||||||
"@testing-library/dom": "^10.4.0",
|
"@testing-library/dom": "^10.4.0",
|
||||||
"@testing-library/jest-dom": "^6.6.3",
|
"@testing-library/jest-dom": "^6.6.3",
|
||||||
"@testing-library/react": "^16.3.0",
|
"@testing-library/react": "^16.3.0",
|
||||||
@ -2461,6 +2466,76 @@
|
|||||||
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@fortawesome/fontawesome-common-types": {
|
||||||
|
"version": "6.7.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.7.2.tgz",
|
||||||
|
"integrity": "sha512-Zs+YeHUC5fkt7Mg1l6XTniei3k4bwG/yo3iFUtZWd/pMx9g3fdvkSK9E0FOC+++phXOka78uJcYb8JaFkW52Xg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@fortawesome/fontawesome-svg-core": {
|
||||||
|
"version": "6.7.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-6.7.2.tgz",
|
||||||
|
"integrity": "sha512-yxtOBWDrdi5DD5o1pmVdq3WMCvnobT0LU6R8RyyVXPvFRd2o79/0NCuQoCjNTeZz9EzA9xS3JxNWfv54RIHFEA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@fortawesome/fontawesome-common-types": "6.7.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@fortawesome/free-brands-svg-icons": {
|
||||||
|
"version": "6.7.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@fortawesome/free-brands-svg-icons/-/free-brands-svg-icons-6.7.2.tgz",
|
||||||
|
"integrity": "sha512-zu0evbcRTgjKfrr77/2XX+bU+kuGfjm0LbajJHVIgBWNIDzrhpRxiCPNT8DW5AdmSsq7Mcf9D1bH0aSeSUSM+Q==",
|
||||||
|
"license": "(CC-BY-4.0 AND MIT)",
|
||||||
|
"dependencies": {
|
||||||
|
"@fortawesome/fontawesome-common-types": "6.7.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@fortawesome/free-regular-svg-icons": {
|
||||||
|
"version": "6.7.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@fortawesome/free-regular-svg-icons/-/free-regular-svg-icons-6.7.2.tgz",
|
||||||
|
"integrity": "sha512-7Z/ur0gvCMW8G93dXIQOkQqHo2M5HLhYrRVC0//fakJXxcF1VmMPsxnG6Ee8qEylA8b8Q3peQXWMNZ62lYF28g==",
|
||||||
|
"license": "(CC-BY-4.0 AND MIT)",
|
||||||
|
"dependencies": {
|
||||||
|
"@fortawesome/fontawesome-common-types": "6.7.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@fortawesome/free-solid-svg-icons": {
|
||||||
|
"version": "6.7.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.7.2.tgz",
|
||||||
|
"integrity": "sha512-GsBrnOzU8uj0LECDfD5zomZJIjrPhIlWU82AHwa2s40FKH+kcxQaBvBo3Z4TxyZHIyX8XTDxsyA33/Vx9eFuQA==",
|
||||||
|
"license": "(CC-BY-4.0 AND MIT)",
|
||||||
|
"dependencies": {
|
||||||
|
"@fortawesome/fontawesome-common-types": "6.7.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@fortawesome/react-fontawesome": {
|
||||||
|
"version": "0.2.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@fortawesome/react-fontawesome/-/react-fontawesome-0.2.2.tgz",
|
||||||
|
"integrity": "sha512-EnkrprPNqI6SXJl//m29hpaNzOp1bruISWaOiRtkMi/xSvHJlzc2j2JAYS7egxt/EbjSNV/k6Xy0AQI6vB2+1g==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"prop-types": "^15.8.1"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@fortawesome/fontawesome-svg-core": "~1 || ~6",
|
||||||
|
"react": ">=16.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@humanwhocodes/config-array": {
|
"node_modules/@humanwhocodes/config-array": {
|
||||||
"version": "0.13.0",
|
"version": "0.13.0",
|
||||||
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz",
|
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz",
|
||||||
|
|||||||
@ -1,5 +1,10 @@
|
|||||||
{
|
{
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@fortawesome/fontawesome-svg-core": "^6.7.2",
|
||||||
|
"@fortawesome/free-brands-svg-icons": "^6.7.2",
|
||||||
|
"@fortawesome/free-regular-svg-icons": "^6.7.2",
|
||||||
|
"@fortawesome/free-solid-svg-icons": "^6.7.2",
|
||||||
|
"@fortawesome/react-fontawesome": "^0.2.2",
|
||||||
"@testing-library/dom": "^10.4.0",
|
"@testing-library/dom": "^10.4.0",
|
||||||
"@testing-library/jest-dom": "^6.6.3",
|
"@testing-library/jest-dom": "^6.6.3",
|
||||||
"@testing-library/react": "^16.3.0",
|
"@testing-library/react": "^16.3.0",
|
||||||
@ -15,7 +20,7 @@
|
|||||||
"web-vitals": "^2.1.4"
|
"web-vitals": "^2.1.4"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "react-scripts start",
|
"start": "export PORT=9010 && react-scripts start",
|
||||||
"build": "react-scripts build",
|
"build": "react-scripts build",
|
||||||
"test": "react-scripts test",
|
"test": "react-scripts test",
|
||||||
"eject": "react-scripts eject"
|
"eject": "react-scripts eject"
|
||||||
|
|||||||
@ -1,24 +1,22 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import logo from './logo.svg';
|
|
||||||
import './App.css';
|
import './App.css';
|
||||||
|
import { TabView } from './components/navigation/TabView';
|
||||||
|
import Home from './pages/home/Home';
|
||||||
|
import { faCalendar, faUser } from '@fortawesome/free-solid-svg-icons';
|
||||||
|
import { faHome } from '@fortawesome/free-solid-svg-icons';
|
||||||
|
|
||||||
|
const tabs = [
|
||||||
|
{ id: 'home', label: 'Home', component: Home, icon: faHome },
|
||||||
|
{ id: 'calendar', label: 'Calendar', component: Home, icon: faCalendar },
|
||||||
|
{ id: 'profile', label: 'Profile', component: Home, icon: faUser }
|
||||||
|
];
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
return (
|
return (
|
||||||
<div className="App">
|
<div className="App">
|
||||||
<header className="App-header">
|
<TabView
|
||||||
<img src={logo} className="App-logo" alt="logo" />
|
tabs={tabs}
|
||||||
<p>
|
/>
|
||||||
Edit <code>src/App.tsx</code> and save to reload.
|
|
||||||
</p>
|
|
||||||
<a
|
|
||||||
className="App-link"
|
|
||||||
href="https://reactjs.org"
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
>
|
|
||||||
Learn React
|
|
||||||
</a>
|
|
||||||
</header>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
72
frontend/src/components/navigation/TabView.css
Normal file
72
frontend/src/components/navigation/TabView.css
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
.tab-container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
height: 100vh;
|
||||||
|
width: 100%;
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
background-color: #f8fafc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-bar {
|
||||||
|
display: flex;
|
||||||
|
background-color: #ffffff;
|
||||||
|
border-top: 1px solid #e2e8f0;
|
||||||
|
margin-top: auto;
|
||||||
|
box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.05);
|
||||||
|
border-radius: 16px 16px 0 0;
|
||||||
|
padding: 5px 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-bar-item {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 12px 0;
|
||||||
|
background: none;
|
||||||
|
border: none;
|
||||||
|
cursor: pointer;
|
||||||
|
color: #64748b;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
border-radius: 12px;
|
||||||
|
margin: 0 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-bar-item:hover {
|
||||||
|
color: #334155;
|
||||||
|
background-color: #f1f5f9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-bar-item.active {
|
||||||
|
color: #3182ce;
|
||||||
|
background-color: #ebf8ff;
|
||||||
|
box-shadow: 0 2px 6px rgba(49, 130, 206, 0.15);
|
||||||
|
transform: translateY(-2px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-icon {
|
||||||
|
font-size: 22px;
|
||||||
|
margin-bottom: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-label {
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 600;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-content {
|
||||||
|
flex: 1;
|
||||||
|
overflow: auto;
|
||||||
|
padding: 20px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
background-color: #ffffff;
|
||||||
|
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.05);
|
||||||
|
margin-bottom: -20px;
|
||||||
|
}
|
||||||
74
frontend/src/components/navigation/TabView.tsx
Normal file
74
frontend/src/components/navigation/TabView.tsx
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
import React, { useState, useEffect } from 'react';
|
||||||
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||||
|
import { IconDefinition } from '@fortawesome/fontawesome-svg-core';
|
||||||
|
import './TabView.css';
|
||||||
|
|
||||||
|
interface TabBarProps {
|
||||||
|
tabs: {
|
||||||
|
id: string;
|
||||||
|
label: string;
|
||||||
|
icon?: React.ReactNode | IconDefinition;
|
||||||
|
component: React.ComponentType<any>;
|
||||||
|
}[];
|
||||||
|
activeTab?: string;
|
||||||
|
onTabChange?: (tabId: string) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const TabView: React.FC<TabBarProps> = ({
|
||||||
|
tabs,
|
||||||
|
activeTab,
|
||||||
|
onTabChange
|
||||||
|
}) => {
|
||||||
|
const [active, setActive] = useState(activeTab || tabs[0]?.id || '');
|
||||||
|
const [ActiveComponent, setActiveComponent] = useState<React.ComponentType<any> | null>(null);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (activeTab && activeTab !== active) {
|
||||||
|
setActive(activeTab);
|
||||||
|
}
|
||||||
|
}, [activeTab, active]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const activeTabData = tabs.find(tab => tab.id === active);
|
||||||
|
if (activeTabData) {
|
||||||
|
setActiveComponent(() => activeTabData.component);
|
||||||
|
}
|
||||||
|
}, [active, tabs]);
|
||||||
|
|
||||||
|
const handleTabClick = (tabId: string) => {
|
||||||
|
setActive(tabId);
|
||||||
|
onTabChange?.(tabId);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="tab-container">
|
||||||
|
<div className="tab-content">
|
||||||
|
{ActiveComponent && <ActiveComponent />}
|
||||||
|
</div>
|
||||||
|
<div className="tab-bar">
|
||||||
|
{tabs.map(tab => (
|
||||||
|
<button
|
||||||
|
key={tab.id}
|
||||||
|
className={`tab-bar-item ${active === tab.id ? 'active' : ''}`}
|
||||||
|
onClick={() => handleTabClick(tab.id)}
|
||||||
|
aria-selected={active === tab.id}
|
||||||
|
role="tab"
|
||||||
|
>
|
||||||
|
{tab.icon && (
|
||||||
|
<span className="tab-icon">
|
||||||
|
{React.isValidElement(tab.icon) ? (
|
||||||
|
tab.icon
|
||||||
|
) : (
|
||||||
|
<FontAwesomeIcon icon={tab.icon as IconDefinition} />
|
||||||
|
)}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
<span className="tab-label">{tab.label}</span>
|
||||||
|
</button>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default TabView;
|
||||||
1
frontend/src/components/navigation/index.ts
Normal file
1
frontend/src/components/navigation/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export { default as TabView } from './TabView';
|
||||||
52
frontend/src/components/ui/FontAwesomeIcons.tsx
Normal file
52
frontend/src/components/ui/FontAwesomeIcons.tsx
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||||
|
import { library } from '@fortawesome/fontawesome-svg-core';
|
||||||
|
import {
|
||||||
|
faCheck,
|
||||||
|
faTimes,
|
||||||
|
faSpinner,
|
||||||
|
faEdit,
|
||||||
|
faTrash,
|
||||||
|
faPlus
|
||||||
|
} from '@fortawesome/free-solid-svg-icons';
|
||||||
|
import {
|
||||||
|
faCalendar,
|
||||||
|
faCircle
|
||||||
|
} from '@fortawesome/free-regular-svg-icons';
|
||||||
|
import {
|
||||||
|
faGithub,
|
||||||
|
faTwitter
|
||||||
|
} from '@fortawesome/free-brands-svg-icons';
|
||||||
|
import { IconName, IconPrefix } from '@fortawesome/fontawesome-svg-core';
|
||||||
|
|
||||||
|
// Add icons to library
|
||||||
|
library.add(
|
||||||
|
faCheck,
|
||||||
|
faTimes,
|
||||||
|
faSpinner,
|
||||||
|
faEdit,
|
||||||
|
faTrash,
|
||||||
|
faPlus,
|
||||||
|
faCalendar,
|
||||||
|
faCircle,
|
||||||
|
faGithub,
|
||||||
|
faTwitter
|
||||||
|
);
|
||||||
|
|
||||||
|
export { FontAwesomeIcon };
|
||||||
|
export const iconNames: Record<string, [IconPrefix, IconName]> = {
|
||||||
|
// Solid
|
||||||
|
check: ['fas', 'check'],
|
||||||
|
times: ['fas', 'times'],
|
||||||
|
spinner: ['fas', 'spinner'],
|
||||||
|
edit: ['fas', 'edit'],
|
||||||
|
trash: ['fas', 'trash'],
|
||||||
|
plus: ['fas', 'plus'],
|
||||||
|
|
||||||
|
// Regular
|
||||||
|
calendar: ['far', 'calendar'],
|
||||||
|
circle: ['far', 'circle'],
|
||||||
|
|
||||||
|
// Brands
|
||||||
|
github: ['fab', 'github'],
|
||||||
|
twitter: ['fab', 'twitter']
|
||||||
|
};
|
||||||
@ -3,6 +3,7 @@ import ReactDOM from 'react-dom/client';
|
|||||||
import './index.css';
|
import './index.css';
|
||||||
import App from './App';
|
import App from './App';
|
||||||
import reportWebVitals from './reportWebVitals';
|
import reportWebVitals from './reportWebVitals';
|
||||||
|
import './components/ui/FontAwesomeIcons';
|
||||||
|
|
||||||
const root = ReactDOM.createRoot(
|
const root = ReactDOM.createRoot(
|
||||||
document.getElementById('root') as HTMLElement
|
document.getElementById('root') as HTMLElement
|
||||||
|
|||||||
56
frontend/src/pages/home/Home.tsx
Normal file
56
frontend/src/pages/home/Home.tsx
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { FontAwesomeIcon } from '../../components/ui/FontAwesomeIcons';
|
||||||
|
|
||||||
|
const Home: React.FC = () => {
|
||||||
|
return (
|
||||||
|
<div className="home-container">
|
||||||
|
<header className="home-header">
|
||||||
|
<h1>Welcome to Our Application</h1>
|
||||||
|
<p>Your centralized dashboard for all features</p>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<section className="features-section">
|
||||||
|
<div className="feature-card">
|
||||||
|
<div className="feature-icon">
|
||||||
|
<FontAwesomeIcon icon={['fas', 'plus']} />
|
||||||
|
</div>
|
||||||
|
<h2>Create New</h2>
|
||||||
|
<p>Start a new project or task</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="feature-card">
|
||||||
|
<div className="feature-icon">
|
||||||
|
<FontAwesomeIcon icon={['far', 'calendar']} />
|
||||||
|
</div>
|
||||||
|
<h2>Schedule</h2>
|
||||||
|
<p>Manage your upcoming events</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="feature-card">
|
||||||
|
<div className="feature-icon">
|
||||||
|
<FontAwesomeIcon icon={['fas', 'edit']} />
|
||||||
|
</div>
|
||||||
|
<h2>Edit</h2>
|
||||||
|
<p>Modify your existing content</p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section className="quick-links">
|
||||||
|
<h2>Quick Links</h2>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<a href="#dashboard">Dashboard</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="#profile">Profile Settings</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="#help">Help & Support</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Home;
|
||||||
4281
package-lock.json
generated
Normal file
4281
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
9
package.json
Normal file
9
package.json
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"dependencies": {
|
||||||
|
"@fortawesome/fontawesome-svg-core": "^6.7.2",
|
||||||
|
"@fortawesome/free-solid-svg-icons": "^6.7.2",
|
||||||
|
"@fortawesome/react-fontawesome": "^0.2.2",
|
||||||
|
"@react-navigation/bottom-tabs": "^7.3.10",
|
||||||
|
"@react-navigation/native": "^7.1.6"
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user