Initial commit

This commit is contained in:
= 2025-04-15 11:35:00 +03:00
parent e2843615d8
commit 5ed5fde98d
14 changed files with 1310 additions and 45 deletions

63
package-lock.json generated
View File

@ -16,7 +16,10 @@
"@testing-library/jest-dom": "^6.6.3",
"@testing-library/react": "^16.3.0",
"@testing-library/user-event": "^13.5.0",
"axios": "^1.8.4",
"chart.js": "^4.4.8",
"react": "^19.1.0",
"react-chartjs-2": "^5.3.0",
"react-dom": "^19.1.0",
"react-icons": "^5.5.0",
"react-router-dom": "^7.5.0",
@ -3026,6 +3029,12 @@
"@jridgewell/sourcemap-codec": "^1.4.14"
}
},
"node_modules/@kurkle/color": {
"version": "0.3.4",
"resolved": "https://registry.npmjs.org/@kurkle/color/-/color-0.3.4.tgz",
"integrity": "sha512-M5UknZPHRu3DEDWoipU6sE8PdkZ6Z/S+v4dD+Ke8IaNlpdSQah50lz1KtcFBa2vsdOnwbbnxJwVM4wty6udA5w==",
"license": "MIT"
},
"node_modules/@leichtgewicht/ip-codec": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.5.tgz",
@ -4969,6 +4978,32 @@
"node": ">=4"
}
},
"node_modules/axios": {
"version": "1.8.4",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.8.4.tgz",
"integrity": "sha512-eBSYY4Y68NNlHbHBMdeDmKNtDgXWhQsJcGqzO3iLUM0GraQFSS9cVgPX5I9b3lbdFKyYoAEGAZF1DwhTaljNAw==",
"license": "MIT",
"dependencies": {
"follow-redirects": "^1.15.6",
"form-data": "^4.0.0",
"proxy-from-env": "^1.1.0"
}
},
"node_modules/axios/node_modules/form-data": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.2.tgz",
"integrity": "sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==",
"license": "MIT",
"dependencies": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.8",
"es-set-tostringtag": "^2.1.0",
"mime-types": "^2.1.12"
},
"engines": {
"node": ">= 6"
}
},
"node_modules/axobject-query": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz",
@ -5603,6 +5638,18 @@
"node": ">=10"
}
},
"node_modules/chart.js": {
"version": "4.4.8",
"resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.4.8.tgz",
"integrity": "sha512-IkGZlVpXP+83QpMm4uxEiGqSI7jFizwVtF3+n5Pc3k7sMO+tkd0qxh2OzLhenM0K80xtmAONWGBn082EiBQSDA==",
"license": "MIT",
"dependencies": {
"@kurkle/color": "^0.3.0"
},
"engines": {
"pnpm": ">=8"
}
},
"node_modules/check-types": {
"version": "11.2.3",
"resolved": "https://registry.npmjs.org/check-types/-/check-types-11.2.3.tgz",
@ -13701,6 +13748,12 @@
"node": ">= 0.10"
}
},
"node_modules/proxy-from-env": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
"license": "MIT"
},
"node_modules/psl": {
"version": "1.15.0",
"resolved": "https://registry.npmjs.org/psl/-/psl-1.15.0.tgz",
@ -13860,6 +13913,16 @@
"integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==",
"license": "MIT"
},
"node_modules/react-chartjs-2": {
"version": "5.3.0",
"resolved": "https://registry.npmjs.org/react-chartjs-2/-/react-chartjs-2-5.3.0.tgz",
"integrity": "sha512-UfZZFnDsERI3c3CZGxzvNJd02SHjaSJ8kgW1djn65H1KK8rehwTjyrRKOG3VTMG8wtHZ5rgAO5oTHtHi9GCCmw==",
"license": "MIT",
"peerDependencies": {
"chart.js": "^4.1.1",
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
}
},
"node_modules/react-dev-utils": {
"version": "12.0.1",
"resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-12.0.1.tgz",

View File

@ -13,6 +13,7 @@
"@testing-library/user-event": "^13.5.0",
"axios": "^1.8.4",
"react": "^19.1.0",
"react-chartjs-2": "^5.3.0",
"react-dom": "^19.1.0",
"react-icons": "^5.5.0",
"react-router-dom": "^7.5.0",

BIN
src/assets/logo2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

@ -15,7 +15,7 @@ import {
faQuestionCircle
} from '@fortawesome/free-solid-svg-icons';
import './navbar.css';
import logo from '../assets/logo.png';
import logo from '../assets/logo2.png';
const Navbar = ({
user,
@ -93,7 +93,7 @@ const Navbar = ({
<div className="navbar-left">
<div className="logo-container" onClick={() => navigate('/dashboard')}>
<img src={logo} alt="Company Logo" className="navbar-logo" />
<span className="navbar-brand">Priente Software License Dashboard </span>
<span className="navbar-brand">Software License Dashboard </span>
</div>
<form className="search-bar" onSubmit={handleSearch}>

View File

@ -1,12 +1,111 @@
import React from 'react';
import './dashboard.css';
const LicenseDistributionPage = () => {
// Sample data
const licenseStats = [
{ label: 'Active Licenses', value: '1,245', change: '+5%' },
{ label: 'Expired Licenses', value: '89', change: '-2%' },
{ label: 'Pending Activations', value: '32', change: '+12%' },
{ label: 'Total Revenue', value: '$48,750', change: '+8%' },
];
const recentDistributions = [
{ id: 'LIC-1001', product: 'Business Suite', distributor: 'TechDistro', date: '2023-05-15', status: 'Active' },
{ id: 'LIC-1002', product: 'Security Pro', distributor: 'SoftLink', date: '2023-05-14', status: 'Pending' },
{ id: 'LIC-1003', product: 'Design Master', distributor: 'DigitalOne', date: '2023-05-12', status: 'Active' },
{ id: 'LIC-1004', product: 'Business Suite', distributor: 'TechDistro', date: '2023-05-10', status: 'Expired' },
];
return (
<div>
<h2>Lisans Dağıtımı</h2>
<p>Lisans dağıtım işlemleri detayları.</p>
<div className="dashboard-container">
<h2 className="dashboard-header">License Distribution Management</h2>
<div className="stats-grid">
{licenseStats.map((stat, index) => (
<div key={index} className="stat-card">
<div className="stat-value">{stat.value}</div>
<div className="stat-label">{stat.label}</div>
<small style={{ color: stat.change.startsWith('+') ? '#27ae60' : '#e74c3c' }}>
{stat.change} from last month
</small>
</div>
))}
</div>
<div className="dashboard-card">
<h3 className="card-title">Recent License Distributions</h3>
<div className="search-filter">
<input type="text" className="search-box" placeholder="Search licenses..." />
<select className="filter-select">
<option>All Status</option>
<option>Active</option>
<option>Pending</option>
<option>Expired</option>
</select>
</div>
<div className="table-container">
<table className="data-table">
<thead>
<tr>
<th>License ID</th>
<th>Product</th>
<th>Distributor</th>
<th>Date</th>
<th>Status</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{recentDistributions.map((license, index) => (
<tr key={index}>
<td>{license.id}</td>
<td>{license.product}</td>
<td>{license.distributor}</td>
<td>{license.date}</td>
<td>
<span style={{
padding: '4px 8px',
borderRadius: '12px',
backgroundColor:
license.status === 'Active' ? '#d5f5e3' :
license.status === 'Pending' ? '#fef9e7' : '#fadbd8',
color:
license.status === 'Active' ? '#27ae60' :
license.status === 'Pending' ? '#f39c12' : '#e74c3c'
}}>
{license.status}
</span>
</td>
<td>
<button className="action-btn">View</button>
<button className="action-btn secondary">Edit</button>
</td>
</tr>
))}
</tbody>
</table>
</div>
</div>
<div className="dashboard-card">
<h3 className="card-title">License Distribution Analytics</h3>
<div className="chart-container">
{/* This would be replaced with an actual chart component */}
<div style={{
background: '#f8f9fa',
height: '100%',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
color: '#7f8c8d'
}}>
[License Distribution Chart - Monthly Trends]
</div>
</div>
</div>
</div>
);
};
export default LicenseDistributionPage;
export default LicenseDistributionPage;

View File

@ -1,12 +1,170 @@
import React from 'react';
import './dashboard.css';
const OrderManagementPage = () => {
const orderStats = [
{ label: 'Total Orders', value: '328', change: '+15%' },
{ label: 'Pending Orders', value: '24', change: '-3%' },
{ label: 'Completed Orders', value: '289', change: '+18%' },
{ label: 'Avg. Processing Time', value: '2.4 days', change: '-0.5' },
];
const recentOrders = [
{ id: 'ORD-2023-1056', customer: 'ABC Corp', product: 'Business Suite', amount: '$1,200', date: '2023-05-15', status: 'Processing' },
{ id: 'ORD-2023-1055', customer: 'XYZ Ltd', product: 'Security Pro', amount: '$850', date: '2023-05-14', status: 'Shipped' },
{ id: 'ORD-2023-1054', customer: 'Acme Inc', product: 'Design Master', amount: '$650', date: '2023-05-13', status: 'Completed' },
{ id: 'ORD-2023-1053', customer: 'Global Tech', product: 'Business Suite', amount: '$2,400', date: '2023-05-12', status: 'Completed' },
];
return (
<div>
<h2>Sipariş Yönetimi</h2>
<p>Sipariş yönetimi ile ilgili içerikler.</p>
<div className="dashboard-container">
<h2 className="dashboard-header">Order Management System</h2>
<div className="stats-grid">
{orderStats.map((stat, index) => (
<div key={index} className="stat-card">
<div className="stat-value">{stat.value}</div>
<div className="stat-label">{stat.label}</div>
<small style={{ color: stat.change.startsWith('+') ? '#27ae60' : stat.change.startsWith('-') ? '#e74c3c' : '#3498db' }}>
{stat.change.startsWith('-') ? stat.change : `+${stat.change}`} from last month
</small>
</div>
))}
</div>
<div className="dashboard-card">
<h3 className="card-title">Recent Orders</h3>
<div className="search-filter">
<input type="text" className="search-box" placeholder="Search orders..." />
<select className="filter-select">
<option>All Status</option>
<option>Processing</option>
<option>Shipped</option>
<option>Completed</option>
<option>Cancelled</option>
</select>
</div>
<div className="table-container">
<table className="data-table">
<thead>
<tr>
<th>Order ID</th>
<th>Customer</th>
<th>Product</th>
<th>Amount</th>
<th>Date</th>
<th>Status</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{recentOrders.map((order, index) => (
<tr key={index}>
<td>{order.id}</td>
<td>{order.customer}</td>
<td>{order.product}</td>
<td>{order.amount}</td>
<td>{order.date}</td>
<td>
<span style={{
padding: '4px 8px',
borderRadius: '12px',
backgroundColor:
order.status === 'Completed' ? '#d5f5e3' :
order.status === 'Processing' ? '#fef9e7' :
order.status === 'Shipped' ? '#d6eaf8' : '#fadbd8',
color:
order.status === 'Completed' ? '#27ae60' :
order.status === 'Processing' ? '#f39c12' :
order.status === 'Shipped' ? '#3498db' : '#e74c3c'
}}>
{order.status}
</span>
</td>
<td>
<button className="action-btn">Details</button>
<button className="action-btn secondary">Track</button>
{order.status === 'Processing' && (
<button className="action-btn danger">Cancel</button>
)}
</td>
</tr>
))}
</tbody>
</table>
</div>
</div>
<div className="dashboard-card">
<h3 className="card-title">Order Fulfillment Workflow</h3>
<div style={{ display: 'flex', justifyContent: 'space-between', marginTop: '20px' }}>
<div style={{ textAlign: 'center', flex: 1 }}>
<div style={{
width: '60px',
height: '60px',
borderRadius: '50%',
backgroundColor: '#3498db',
color: 'white',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
margin: '0 auto 10px',
fontSize: '24px'
}}>1</div>
<h4>Order Received</h4>
<p style={{ color: '#7f8c8d' }}>Customer places order</p>
</div>
<div style={{ textAlign: 'center', flex: 1 }}>
<div style={{
width: '60px',
height: '60px',
borderRadius: '50%',
backgroundColor: '#3498db',
color: 'white',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
margin: '0 auto 10px',
fontSize: '24px'
}}>2</div>
<h4>Processing</h4>
<p style={{ color: '#7f8c8d' }}>Verification & preparation</p>
</div>
<div style={{ textAlign: 'center', flex: 1 }}>
<div style={{
width: '60px',
height: '60px',
borderRadius: '50%',
backgroundColor: '#3498db',
color: 'white',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
margin: '0 auto 10px',
fontSize: '24px'
}}>3</div>
<h4>License Generation</h4>
<p style={{ color: '#7f8c8d' }}>Create & validate license</p>
</div>
<div style={{ textAlign: 'center', flex: 1 }}>
<div style={{
width: '60px',
height: '60px',
borderRadius: '50%',
backgroundColor: '#3498db',
color: 'white',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
margin: '0 auto 10px',
fontSize: '24px'
}}>4</div>
<h4>Delivery</h4>
<p style={{ color: '#7f8c8d' }}>Send to customer</p>
</div>
</div>
</div>
</div>
);
};
export default OrderManagementPage;
export default OrderManagementPage;

View File

@ -1,12 +1,164 @@
import React from 'react';
import './dashboard.css';
const PaymentBillingPage = () => {
const paymentStats = [
{ label: 'Total Revenue', value: '$86,450', change: '+12%' },
{ label: 'Pending Payments', value: '$5,720', change: '-3%' },
{ label: 'Avg. Payment Time', value: '2.1 days', change: '-0.3' },
{ label: 'Successful Transactions', value: '94.7%', change: '+1.2%' },
];
const recentTransactions = [
{ id: 'TXN-58741', invoice: 'INV-2023-1056', amount: '$1,200', date: '2023-05-15', method: 'Credit Card', status: 'Completed' },
{ id: 'TXN-58740', invoice: 'INV-2023-1055', amount: '$850', date: '2023-05-14', method: 'PayPal', status: 'Completed' },
{ id: 'TXN-58739', invoice: 'INV-2023-1054', amount: '$650', date: '2023-05-13', method: 'Bank Transfer', status: 'Pending' },
{ id: 'TXN-58738', invoice: 'INV-2023-1053', amount: '$2,400', date: '2023-05-12', method: 'Credit Card', status: 'Failed' },
];
const upcomingInvoices = [
{ invoice: 'INV-2023-1057', client: 'ABC Corp', amount: '$1,500', dueDate: '2023-05-20', status: 'Unpaid' },
{ invoice: 'INV-2023-1058', client: 'XYZ Ltd', amount: '$950', dueDate: '2023-05-21', status: 'Unpaid' },
{ invoice: 'INV-2023-1059', client: 'Acme Inc', amount: '$2,100', dueDate: '2023-05-22', status: 'Unpaid' },
];
return (
<div>
<h2>Ödeme & Fatura</h2>
<p>Ödeme ve fatura işlemleri bilgileri.</p>
<div className="dashboard-container">
<h2 className="dashboard-header">Payment & Billing Management</h2>
<div className="stats-grid">
{paymentStats.map((stat, index) => (
<div key={index} className="stat-card">
<div className="stat-value">{stat.value}</div>
<div className="stat-label">{stat.label}</div>
<small style={{ color: stat.change.startsWith('+') ? '#27ae60' : stat.change.startsWith('-') ? '#e74c3c' : '#3498db' }}>
{stat.change.startsWith('-') ? stat.change : `+${stat.change}`} from last month
</small>
</div>
))}
</div>
<div className="dashboard-card">
<h3 className="card-title">Recent Transactions</h3>
<div className="search-filter">
<input type="text" className="search-box" placeholder="Search transactions..." />
<select className="filter-select">
<option>All Status</option>
<option>Completed</option>
<option>Pending</option>
<option>Failed</option>
</select>
</div>
<div className="table-container">
<table className="data-table">
<thead>
<tr>
<th>Transaction ID</th>
<th>Invoice</th>
<th>Amount</th>
<th>Date</th>
<th>Method</th>
<th>Status</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{recentTransactions.map((txn, index) => (
<tr key={index}>
<td>{txn.id}</td>
<td>{txn.invoice}</td>
<td>{txn.amount}</td>
<td>{txn.date}</td>
<td>{txn.method}</td>
<td>
<span style={{
padding: '4px 8px',
borderRadius: '12px',
backgroundColor:
txn.status === 'Completed' ? '#d5f5e3' :
txn.status === 'Pending' ? '#fef9e7' : '#fadbd8',
color:
txn.status === 'Completed' ? '#27ae60' :
txn.status === 'Pending' ? '#f39c12' : '#e74c3c'
}}>
{txn.status}
</span>
</td>
<td>
<button className="action-btn">Details</button>
{txn.status === 'Pending' && (
<button className="action-btn secondary">Remind</button>
)}
{txn.status === 'Failed' && (
<button className="action-btn danger">Retry</button>
)}
</td>
</tr>
))}
</tbody>
</table>
</div>
</div>
<div className="dashboard-card">
<h3 className="card-title">Upcoming Invoices</h3>
<div className="table-container">
<table className="data-table">
<thead>
<tr>
<th>Invoice</th>
<th>Client</th>
<th>Amount</th>
<th>Due Date</th>
<th>Status</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{upcomingInvoices.map((invoice, index) => (
<tr key={index}>
<td>{invoice.invoice}</td>
<td>{invoice.client}</td>
<td>{invoice.amount}</td>
<td>{invoice.dueDate}</td>
<td>
<span style={{
padding: '4px 8px',
borderRadius: '12px',
backgroundColor: '#fef9e7',
color: '#f39c12'
}}>
{invoice.status}
</span>
</td>
<td>
<button className="action-btn">View</button>
<button className="action-btn secondary">Send Reminder</button>
</td>
</tr>
))}
</tbody>
</table>
</div>
</div>
<div className="dashboard-card">
<h3 className="card-title">Revenue Analytics</h3>
<div className="chart-container">
{/* This would be replaced with an actual chart component */}
<div style={{
background: '#f8f9fa',
height: '100%',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
color: '#7f8c8d'
}}>
[Revenue Chart - Monthly Trends by Payment Method]
</div>
</div>
</div>
</div>
);
};
export default PaymentBillingPage;
export default PaymentBillingPage;

View File

@ -1,12 +1,188 @@
import React from 'react';
import './dashboard.css';
const RetailerFeedbackPage = () => {
const feedbackStats = [
{ label: 'Total Feedback', value: '142', change: '+8%' },
{ label: 'Average Rating', value: '4.2/5', change: '+0.1' },
{ label: 'Positive Feedback', value: '87%', change: '+3%' },
{ label: 'Response Rate', value: '92%', change: '+2%' },
];
const recentFeedback = [
{ id: 'FB-1056', retailer: 'Tech Haven', rating: 5, comment: 'Excellent service and fast response times!', date: '2023-05-15', status: 'Responded' },
{ id: 'FB-1055', retailer: 'Digital World', rating: 4, comment: 'Good products but delivery could be faster', date: '2023-05-14', status: 'Pending' },
{ id: 'FB-1054', retailer: 'Software Plus', rating: 3, comment: 'Had some issues with license activation', date: '2023-05-13', status: 'In Progress' },
{ id: 'FB-1053', retailer: 'CompuZone', rating: 5, comment: 'Best software distributor we work with', date: '2023-05-12', status: 'Responded' },
];
const ratingDistribution = [
{ stars: 5, count: 85, percent: 60 },
{ stars: 4, count: 32, percent: 22 },
{ stars: 3, count: 15, percent: 10 },
{ stars: 2, count: 6, percent: 4 },
{ stars: 1, count: 4, percent: 3 },
];
return (
<div>
<h2>Perakende Geri Bildirim</h2>
<p>Perakende ile gelen geri bildirimler.</p>
<div className="dashboard-container">
<h2 className="dashboard-header">Retailer Feedback Management</h2>
<div className="stats-grid">
{feedbackStats.map((stat, index) => (
<div key={index} className="stat-card">
<div className="stat-value">{stat.value}</div>
<div className="stat-label">{stat.label}</div>
<small style={{ color: stat.change.startsWith('+') ? '#27ae60' : '#e74c3c' }}>
{stat.change} from last month
</small>
</div>
))}
</div>
<div className="dashboard-card">
<h3 className="card-title">Recent Feedback</h3>
<div className="search-filter">
<input type="text" className="search-box" placeholder="Search feedback..." />
<select className="filter-select">
<option>All Status</option>
<option>Responded</option>
<option>Pending</option>
<option>In Progress</option>
</select>
</div>
<div className="table-container">
<table className="data-table">
<thead>
<tr>
<th>Feedback ID</th>
<th>Retailer</th>
<th>Rating</th>
<th>Comment</th>
<th>Date</th>
<th>Status</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{recentFeedback.map((feedback, index) => (
<tr key={index}>
<td>{feedback.id}</td>
<td>{feedback.retailer}</td>
<td>
<div style={{ display: 'flex' }}>
{[...Array(5)].map((_, i) => (
<span key={i} style={{
color: i < feedback.rating ? '#f39c12' : '#ddd',
fontSize: '18px'
}}></span>
))}
</div>
</td>
<td style={{ maxWidth: '300px' }}>{feedback.comment}</td>
<td>{feedback.date}</td>
<td>
<span style={{
padding: '4px 8px',
borderRadius: '12px',
backgroundColor:
feedback.status === 'Responded' ? '#d5f5e3' :
feedback.status === 'Pending' ? '#fadbd8' : '#fef9e7',
color:
feedback.status === 'Responded' ? '#27ae60' :
feedback.status === 'Pending' ? '#e74c3c' : '#f39c12'
}}>
{feedback.status}
</span>
</td>
<td>
<button className="action-btn">View</button>
{feedback.status !== 'Responded' && (
<button className="action-btn secondary">Respond</button>
)}
</td>
</tr>
))}
</tbody>
</table>
</div>
</div>
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '20px' }}>
<div className="dashboard-card">
<h3 className="card-title">Rating Distribution</h3>
<div style={{ marginTop: '20px' }}>
{ratingDistribution.map((item, index) => (
<div key={index} style={{ marginBottom: '10px' }}>
<div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: '5px' }}>
<span>
{[...Array(item.stars)].map((_, i) => (
<span key={i} style={{ color: '#f39c12' }}></span>
))}
</span>
<span>{item.count} ({item.percent}%)</span>
</div>
<div style={{
height: '10px',
backgroundColor: '#ecf0f1',
borderRadius: '5px',
overflow: 'hidden'
}}>
<div style={{
width: `${item.percent}%`,
height: '100%',
backgroundColor: '#f39c12',
borderRadius: '5px'
}}></div>
</div>
</div>
))}
</div>
</div>
<div className="dashboard-card">
<h3 className="card-title">Feedback Response</h3>
<div style={{
height: '250px',
display: 'flex',
alignItems: 'center',
justifyContent: 'center'
}}>
{/* This would be replaced with an actual chart component */}
<div style={{
background: '#f8f9fa',
width: '100%',
height: '200px',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
color: '#7f8c8d'
}}>
[Response Time and Satisfaction Chart]
</div>
</div>
<div style={{
display: 'flex',
justifyContent: 'space-around',
marginTop: '20px',
textAlign: 'center'
}}>
<div>
<div style={{ fontSize: '24px', fontWeight: 'bold', color: '#27ae60' }}>92%</div>
<div style={{ color: '#7f8c8d' }}>Response Rate</div>
</div>
<div>
<div style={{ fontSize: '24px', fontWeight: 'bold', color: '#3498db' }}>6.2h</div>
<div style={{ color: '#7f8c8d' }}>Avg. Response Time</div>
</div>
<div>
<div style={{ fontSize: '24px', fontWeight: 'bold', color: '#f39c12' }}>87%</div>
<div style={{ color: '#7f8c8d' }}>Satisfaction After Response</div>
</div>
</div>
</div>
</div>
</div>
);
};
export default RetailerFeedbackPage;
export default RetailerFeedbackPage;

View File

@ -1,12 +1,84 @@
// SalesPerformancePage.jsx
import React from 'react';
import { Line } from 'react-chartjs-2';
import { Chart as ChartJS } from 'chart.js/auto';
const SalesPerformancePage = () => {
const salesData = {
labels: ['Ocak', 'Şubat', 'Mart', 'Nisan', 'Mayıs', 'Haziran'],
datasets: [
{
label: 'Aylık Satışlar (TL)',
data: [65000, 59000, 80000, 81000, 56000, 95000],
borderColor: '#4A90E2',
tension: 0.4,
},
],
};
const regionalSales = {
'İstanbul': 45,
'Ankara': 25,
'İzmir': 15,
'Diğer': 15
};
return (
<div>
<h2>Satış Performansı</h2>
<p>Satış performans analizleri burada.</p>
<div className="dashboard-page">
<h2 className="page-title">Satış Performansı</h2>
<div className="grid-container">
<div className="chart-card">
<h3>Aylık Satış Trendi</h3>
<Line data={salesData} />
</div>
<div className="metrics-card">
<h3>Bölgesel Dağılım</h3>
<div className="regional-distribution">
{Object.entries(regionalSales).map(([region, percent]) => (
<div key={region} className="region-item">
<div className="region-label">
<span>{region}</span>
<span>{percent}%</span>
</div>
<div className="progress-bar">
<div
className="progress-fill"
style={{ width: `${percent}%` }}
></div>
</div>
</div>
))}
</div>
</div>
<div className="recent-sales">
<h3>Son İşlemler</h3>
<table>
<thead>
<tr>
<th>Tarih</th>
<th>Ürün</th>
<th>Miktar</th>
<th>Durum</th>
</tr>
</thead>
<tbody>
{[...Array(5)].map((_, i) => (
<tr key={i}>
<td>2023-0{i+1}-15</td>
<td>Yazılım Paketi {i+1}</td>
<td>{(i+1)*1450} TL</td>
<td><span className="status completed">Tamamlandı</span></td>
</tr>
))}
</tbody>
</table>
</div>
</div>
</div>
);
};
export default SalesPerformancePage;
export default SalesPerformancePage;

View File

@ -1,12 +1,90 @@
import React from 'react';
// SalesReportsPage.jsx
import React, { useState } from 'react';
const SalesReportsPage = () => {
const [filters, setFilters] = useState({
dateRange: 'month',
productCategory: 'all',
region: 'all'
});
const reports = [...Array(8)].map((_, i) => ({
id: i+1,
date: `2023-Q${Math.floor(i/2)+1}`,
product: `Ürün Kategorisi ${i%3+1}`,
region: ['İstanbul', 'Ankara', 'İzmir'][i%3],
total: (i+1)*17500,
status: ['pending', 'completed'][i%2]
}));
return (
<div>
<h2>Satış Raporları</h2>
<p>Satış raporlarına ait detaylar.</p>
<div className="dashboard-page">
<h2 className="page-title">Satış Raporları</h2>
<div className="report-filters">
<select
value={filters.dateRange}
onChange={(e) => setFilters({...filters, dateRange: e.target.value})}
>
<option value="week">Son 1 Hafta</option>
<option value="month">Son 1 Ay</option>
<option value="quarter">Son 3 Ay</option>
</select>
<select
value={filters.productCategory}
onChange={(e) => setFilters({...filters, productCategory: e.target.value})}
>
<option value="all">Tüm Kategoriler</option>
<option value="1">ERP Çözümleri</option>
<option value="2">Bulut Hizmetleri</option>
</select>
<select
value={filters.region}
onChange={(e) => setFilters({...filters, region: e.target.value})}
>
<option value="all">Tüm Bölgeler</option>
<option value="istanbul">İstanbul</option>
<option value="ankara">Ankara</option>
</select>
</div>
<div className="report-table">
<table>
<thead>
<tr>
<th>Çeyrek</th>
<th>Ürün Kategorisi</th>
<th>Bölge</th>
<th>Toplam Satış</th>
<th>Durum</th>
<th>İşlemler</th>
</tr>
</thead>
<tbody>
{reports.map(report => (
<tr key={report.id}>
<td>{report.date}</td>
<td>{report.product}</td>
<td>{report.region}</td>
<td>{report.total.toLocaleString()} TL</td>
<td>
<span className={`status ${report.status}`}>
{report.status === 'completed' ? 'Tamamlandı' : 'Beklemede'}
</span>
</td>
<td>
<button className="export-btn pdf">PDF Al</button>
<button className="export-btn excel">Excel'e Aktar</button>
</td>
</tr>
))}
</tbody>
</table>
</div>
</div>
);
};
export default SalesReportsPage;
export default SalesReportsPage;

View File

@ -1,12 +1,106 @@
import React from 'react';
// StockCampaignManagementPage.jsx
import React, { useState } from 'react';
const StockCampaignManagementPage = () => {
const [stock] = useState([
{ id: 1, product: 'ERP Pro Lisans', stock: 45, threshold: 50 },
{ id: 2, product: 'Bulut Depolama 100GB', stock: 23, threshold: 30 },
{ id: 3, product: 'E-Ticaret Entegrasyon', stock: 12, threshold: 20 }
]);
const [campaigns, setCampaigns] = useState([
{ id: 1, name: 'Yazılım Paket İndirimi', status: 'active', discount: 15 },
{ id: 2, name: 'Bulut Depolama Kampanyası', status: 'planned', discount: 20 }
]);
const [newCampaign, setNewCampaign] = useState({
name: '',
discount: '',
startDate: '',
endDate: ''
});
const handleAddCampaign = (e) => {
e.preventDefault();
// Kampanya ekleme mantığı
};
return (
<div>
<h2>Stok & Kampanya Yönetimi</h2>
<p>Stok ve kampanya yönetimi bilgileri.</p>
<div className="dashboard-page">
<h2 className="page-title">Stok & Kampanya Yönetimi</h2>
<div className="management-container">
<div className="stock-section">
<h3>Stok Durumu</h3>
<div className="stock-list">
{stock.map(item => (
<div key={item.id} className="stock-item">
<div className="stock-info">
<span className="product-name">{item.product}</span>
<span className={`stock-quantity ${item.stock < item.threshold ? 'low' : ''}`}>
{item.stock} Adet
</span>
</div>
<div className="progress-bar">
<div
className="progress-fill"
style={{ width: `${(item.stock / item.threshold) * 100}%` }}
></div>
</div>
</div>
))}
</div>
</div>
<div className="campaign-section">
<h3>Aktif Kampanyalar</h3>
<div className="campaign-list">
{campaigns.map(campaign => (
<div key={campaign.id} className={`campaign-card ${campaign.status}`}>
<div className="campaign-header">
<h4>{campaign.name}</h4>
<span className="status-dot"></span>
</div>
<div className="campaign-details">
<span>İndirim: %{campaign.discount}</span>
<span>Durum: {campaign.status === 'active' ? 'Aktif' : 'Planlanan'}</span>
</div>
</div>
))}
</div>
<form onSubmit={handleAddCampaign} className="campaign-form">
<h4>Yeni Kampanya Ekle</h4>
<input
type="text"
placeholder="Kampanya Adı"
value={newCampaign.name}
onChange={(e) => setNewCampaign({...newCampaign, name: e.target.value})}
/>
<input
type="number"
placeholder="İndirim Oranı (%)"
value={newCampaign.discount}
onChange={(e) => setNewCampaign({...newCampaign, discount: e.target.value})}
/>
<div className="date-inputs">
<input
type="date"
value={newCampaign.startDate}
onChange={(e) => setNewCampaign({...newCampaign, startDate: e.target.value})}
/>
<input
type="date"
value={newCampaign.endDate}
onChange={(e) => setNewCampaign({...newCampaign, endDate: e.target.value})}
/>
</div>
<button type="submit" className="add-button">Kampanya Ekle</button>
</form>
</div>
</div>
</div>
);
};
export default StockCampaignManagementPage;
export default StockCampaignManagementPage;

View File

@ -0,0 +1,298 @@
/* styles/dashboard.css */
.dashboard-container {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
max-width: 1200px;
margin: 0 auto;
padding: 20px;
}
.dashboard-header {
color: #2c3e50;
border-bottom: 2px solid #3498db;
padding-bottom: 10px;
margin-bottom: 30px;
}
.dashboard-card {
background: white;
border-radius: 8px;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
padding: 20px;
margin-bottom: 30px;
}
.card-title {
color: #2980b9;
margin-top: 0;
}
.stats-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
gap: 20px;
margin-bottom: 20px;
}
.stat-card {
background: #f8f9fa;
padding: 15px;
border-radius: 6px;
border-left: 4px solid #3498db;
}
.stat-value {
font-size: 24px;
font-weight: bold;
color: #2c3e50;
}
.stat-label {
color: #7f8c8d;
font-size: 14px;
}
.table-container {
overflow-x: auto;
}
.data-table {
width: 100%;
border-collapse: collapse;
margin-top: 20px;
}
.data-table th {
background-color: #3498db;
color: white;
padding: 12px;
text-align: left;
}
.data-table td {
padding: 10px 12px;
border-bottom: 1px solid #ecf0f1;
}
.data-table tr:hover {
background-color: #f8f9fa;
}
.action-btn {
background-color: #3498db;
color: white;
border: none;
padding: 8px 12px;
border-radius: 4px;
cursor: pointer;
margin-right: 5px;
font-size: 14px;
}
.action-btn.secondary {
background-color: #95a5a6;
}
.action-btn.danger {
background-color: #e74c3c;
}
.action-btn:hover {
opacity: 0.9;
}
.chart-container {
height: 300px;
margin: 20px 0;
}
.search-filter {
display: flex;
justify-content: space-between;
margin-bottom: 20px;
}
.search-box {
padding: 10px;
border: 1px solid #ddd;
border-radius: 4px;
width: 300px;
}
.filter-select {
padding: 10px;
border: 1px solid #ddd;
border-radius: 4px;
background: white;
}
.page-title {
color: #2c3e50;
border-bottom: 3px solid #4A90E2;
padding-bottom: 0.5rem;
margin-bottom: 2rem;
}
.grid-container {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 2rem;
}
.chart-card, .metrics-card {
background: white;
padding: 1.5rem;
border-radius: 10px;
box-shadow: 0 2px 15px rgba(0,0,0,0.1);
}
.recent-sales table {
width: 100%;
border-collapse: collapse;
margin-top: 1rem;
}
th, td {
text-align: left;
padding: 12px;
border-bottom: 1px solid #eee;
}
.status {
display: inline-block;
padding: 5px 12px;
border-radius: 20px;
font-size: 0.85rem;
}
.status.completed {
background: #e8f5e9;
color: #2e7d32;
}
.progress-bar {
height: 8px;
background: #eee;
border-radius: 4px;
overflow: hidden;
}
.progress-fill {
height: 100%;
background: #4A90E2;
transition: width 0.3s ease;
}
/* Sales Reports Specific */
.report-filters {
display: flex;
gap: 1rem;
margin-bottom: 2rem;
}
.report-filters select {
padding: 8px 12px;
border: 1px solid #ddd;
border-radius: 5px;
background: white;
}
.export-btn {
padding: 6px 12px;
border: none;
border-radius: 5px;
margin: 2px;
cursor: pointer;
}
.export-btn.pdf { background: #ff4757; color: white; }
.export-btn.excel { background: #2ed573; color: white; }
/* Stock & Campaign Management */
.management-container {
display: grid;
grid-template-columns: 1fr 1.5fr;
gap: 2rem;
}
.stock-item {
background: white;
padding: 1rem;
margin-bottom: 1rem;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0,0,0,0.05);
}
.stock-quantity.low { color: #e74c3c; }
.campaign-card {
background: white;
padding: 1rem;
margin-bottom: 1rem;
border-left: 4px solid;
border-radius: 6px;
}
.campaign-card.active { border-color: #4A90E2; }
.campaign-card.planned { border-color: #f1c40f; }
.campaign-form {
background: #f9f9f9;
padding: 1.5rem;
border-radius: 8px;
margin-top: 2rem;
}
.campaign-form input {
display: block;
width: 100%;
padding: 8px;
margin: 8px 0;
border: 1px solid #ddd;
}
.add-button {
background: #4A90E2;
color: white;
padding: 10px 20px;
border: none;
border-radius: 5px;
cursor: pointer;
margin-top: 1rem;
}
@media (max-width: 768px) {
.management-container {
grid-template-columns: 1fr;
}
.grid-container {
grid-template-columns: 1fr;
}
}

View File

@ -12,31 +12,31 @@ const LoginPage = ({ onLogin }) => {
};
return (
<div className="min-h-screen flex items-center justify-center bg-gray-100">
<div className="bg-white p-8 rounded-lg shadow-md w-96">
<h1 className="text-2xl font-bold text-center mb-6">Software License Dashboard</h1>
<div className="space-y-4">
<div style={styles.loginContainer}>
<div style={styles.loginBox}>
<h1 style={styles.loginTitle}>Software License Dashboard</h1>
<div style={styles.buttonContainer}>
<button
onClick={() => handleLogin('admin')}
className="w-full py-2 px-4 bg-blue-500 text-white rounded hover:bg-blue-600 transition"
style={{ ...styles.loginButton, ...styles.admin }}
>
Login as Admin
</button>
<button
onClick={() => handleLogin('distributor')}
className="w-full py-2 px-4 bg-green-500 text-white rounded hover:bg-green-600 transition"
style={{ ...styles.loginButton, ...styles.distributor }}
>
Login as Distributor
</button>
<button
onClick={() => handleLogin('retailer')}
className="w-full py-2 px-4 bg-purple-500 text-white rounded hover:bg-purple-600 transition"
style={{ ...styles.loginButton, ...styles.retailer }}
>
Login as Retailer
</button>
<button
onClick={() => handleLogin('customer')}
className="w-full py-2 px-4 bg-orange-500 text-white rounded hover:bg-orange-600 transition"
style={{ ...styles.loginButton, ...styles.customer }}
>
Login as Customer
</button>
@ -46,4 +46,78 @@ const LoginPage = ({ onLogin }) => {
);
};
export default LoginPage;
const styles = {
loginContainer: {
minHeight: '100vh',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
background: 'linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%)',
padding: '20px',
},
loginBox: {
background: 'rgba(255, 255, 255, 0.95)',
padding: '2.5rem',
borderRadius: '15px',
boxShadow: '0 8px 30px rgba(0, 0, 0, 0.12)',
width: '100%',
maxWidth: '400px',
position: 'relative',
overflow: 'hidden',
animation: 'fadeInUp 0.6s ease',
},
loginTitle: {
fontSize: '1.8rem',
fontWeight: 700,
color: '#2d3748',
textAlign: 'center',
marginBottom: '2rem',
position: 'relative',
},
buttonContainer: {
display: 'flex',
flexDirection: 'column',
gap: '1rem',
},
loginButton: {
width: '100%',
padding: '0.8rem',
border: 'none',
borderRadius: '8px',
fontSize: '1rem',
fontWeight: '500',
cursor: 'pointer',
transition: 'all 0.3s ease',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
gap: '0.5rem',
position: 'relative',
overflow: 'hidden',
},
loginButtonHover: {
transform: 'translateY(-2px)',
boxShadow: '0 4px 6px rgba(0, 0, 0, 0.1)',
},
loginButtonActive: {
transform: 'translateY(0)',
},
admin: {
background: '#4299e1',
color: 'white',
},
distributor: {
background: '#48bb78',
color: 'white',
},
retailer: {
background: '#9f7aea',
color: 'white',
},
customer: {
background: '#ed8936',
color: 'white',
},
};
export default LoginPage;

View File

@ -15,7 +15,7 @@ const DistributorRoutes = () => {
<Route path="/sales-performance" element={<SalesPerformancePage />} />
<Route path="/order-management" element={<OrderManagementPage />} />
<Route path="/license-distribution" element={<LicenseDistributionPage />} />
<Route path="/stock-management" element={<StockCampaignManagementPage />} />
<Route path="/stock-campaign" element={<StockCampaignManagementPage />} />
<Route path="/payment-billing" element={<PaymentBillingPage />} />
<Route path="/retailer-feedback" element={<RetailerFeedbackPage />} />
<Route path="/sales-reports" element={<SalesReportsPage />} />