First Commit
This commit is contained in:
451
assets/css/admin.css
Normal file
451
assets/css/admin.css
Normal file
@@ -0,0 +1,451 @@
|
||||
/* WP Digital Download - Admin Styles */
|
||||
|
||||
/* Product Metaboxes */
|
||||
.wpdd-metabox-content {
|
||||
padding: 10px 0;
|
||||
}
|
||||
|
||||
.wpdd-metabox-content p {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.wpdd-metabox-content label {
|
||||
display: block;
|
||||
margin-bottom: 5px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.wpdd-metabox-content input[type="text"],
|
||||
.wpdd-metabox-content input[type="number"],
|
||||
.wpdd-metabox-content input[type="email"] {
|
||||
width: 100%;
|
||||
padding: 8px;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.wpdd-metabox-content input[type="checkbox"] {
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.wpdd-metabox-content .description {
|
||||
font-style: italic;
|
||||
color: #666;
|
||||
font-size: 12px;
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
/* Price fields toggle */
|
||||
#wpdd_is_free:checked ~ .wpdd-price-field {
|
||||
opacity: 0.5;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
/* Files Metabox */
|
||||
.wpdd-files-container {
|
||||
padding: 10px 0;
|
||||
}
|
||||
|
||||
#wpdd-files-list {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.wpdd-file-item {
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 4px;
|
||||
margin-bottom: 15px;
|
||||
background: #f9f9f9;
|
||||
}
|
||||
|
||||
.wpdd-file-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 10px 15px;
|
||||
background: #f1f1f1;
|
||||
border-bottom: 1px solid #ddd;
|
||||
}
|
||||
|
||||
.wpdd-file-handle {
|
||||
cursor: move;
|
||||
margin-right: 10px;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.wpdd-file-header input[type="text"] {
|
||||
flex: 1;
|
||||
margin-right: 10px;
|
||||
padding: 5px 8px;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.wpdd-file-content {
|
||||
padding: 15px;
|
||||
}
|
||||
|
||||
.wpdd-file-url {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.wpdd-file-url-input {
|
||||
flex: 1;
|
||||
padding: 8px;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.wpdd-upload-file,
|
||||
.wpdd-remove-file {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.wpdd-remove-file {
|
||||
background: #dc3545;
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 5px 10px;
|
||||
border-radius: 3px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.wpdd-remove-file:hover {
|
||||
background: #c82333;
|
||||
}
|
||||
|
||||
#wpdd-add-file {
|
||||
background: #0073aa;
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 10px 20px;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#wpdd-add-file:hover {
|
||||
background: #005a87;
|
||||
}
|
||||
|
||||
/* Settings Grid */
|
||||
.wpdd-settings-grid {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 30px;
|
||||
}
|
||||
|
||||
.wpdd-setting-group {
|
||||
background: #f9f9f9;
|
||||
padding: 20px;
|
||||
border-radius: 6px;
|
||||
border: 1px solid #e1e5e9;
|
||||
}
|
||||
|
||||
.wpdd-setting-group h4 {
|
||||
margin: 0 0 15px 0;
|
||||
color: #23282d;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.wpdd-setting-group p {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.wpdd-setting-group label {
|
||||
display: block;
|
||||
margin-bottom: 5px;
|
||||
font-weight: 500;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.wpdd-setting-group input[type="text"],
|
||||
.wpdd-setting-group input[type="number"] {
|
||||
width: 100%;
|
||||
padding: 6px 8px;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 3px;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.wpdd-setting-group .description {
|
||||
font-size: 12px;
|
||||
color: #666;
|
||||
font-style: italic;
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
@media (max-width: 782px) {
|
||||
.wpdd-settings-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
/* Stats Metabox */
|
||||
.wpdd-stats p {
|
||||
margin-bottom: 8px;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.wpdd-stats strong {
|
||||
color: #23282d;
|
||||
}
|
||||
|
||||
/* Product List Columns */
|
||||
.column-wpdd_price,
|
||||
.column-wpdd_sales,
|
||||
.column-wpdd_revenue,
|
||||
.column-wpdd_files {
|
||||
width: 10%;
|
||||
}
|
||||
|
||||
/* File Upload Progress */
|
||||
.wpdd-upload-progress {
|
||||
width: 100%;
|
||||
height: 20px;
|
||||
background: #f1f1f1;
|
||||
border-radius: 10px;
|
||||
overflow: hidden;
|
||||
margin: 10px 0;
|
||||
}
|
||||
|
||||
.wpdd-upload-progress-bar {
|
||||
height: 100%;
|
||||
background: #0073aa;
|
||||
transition: width 0.3s;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
/* Drag and Drop Sorting */
|
||||
.wpdd-file-item.ui-sortable-helper {
|
||||
box-shadow: 0 4px 8px rgba(0,0,0,0.2);
|
||||
transform: rotate(2deg);
|
||||
}
|
||||
|
||||
.wpdd-file-item.ui-sortable-placeholder {
|
||||
border: 2px dashed #0073aa;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
/* Admin Dashboard Widgets */
|
||||
.wpdd-sales-summary .wpdd-stats-grid {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 15px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.wpdd-sales-summary .wpdd-stat {
|
||||
text-align: center;
|
||||
padding: 10px;
|
||||
background: #f0f0f1;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.wpdd-sales-summary .wpdd-stat-value {
|
||||
display: block;
|
||||
font-size: 24px;
|
||||
font-weight: 600;
|
||||
color: #2271b1;
|
||||
}
|
||||
|
||||
.wpdd-sales-summary .wpdd-stat-label {
|
||||
display: block;
|
||||
font-size: 12px;
|
||||
color: #646970;
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
/* Orders Page */
|
||||
.wpdd-status {
|
||||
padding: 3px 8px;
|
||||
border-radius: 3px;
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.wpdd-status-completed {
|
||||
background: #d4edda;
|
||||
color: #155724;
|
||||
}
|
||||
|
||||
.wpdd-status-pending {
|
||||
background: #fff3cd;
|
||||
color: #856404;
|
||||
}
|
||||
|
||||
.wpdd-status-failed {
|
||||
background: #f8d7da;
|
||||
color: #721c24;
|
||||
}
|
||||
|
||||
/* Reports Page */
|
||||
.wpdd-date-filter {
|
||||
margin: 20px 0;
|
||||
}
|
||||
|
||||
.wpdd-stats-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
||||
gap: 20px;
|
||||
margin: 30px 0;
|
||||
}
|
||||
|
||||
.wpdd-stat-box {
|
||||
background: white;
|
||||
padding: 20px;
|
||||
border: 1px solid #ccd0d4;
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 1px 3px rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
.wpdd-stat-box h3 {
|
||||
margin: 0 0 10px 0;
|
||||
color: #23282d;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.wpdd-stat-value {
|
||||
font-size: 32px;
|
||||
font-weight: 600;
|
||||
color: #2271b1;
|
||||
margin: 0;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.wpdd-reports-tables {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 30px;
|
||||
margin-top: 30px;
|
||||
}
|
||||
|
||||
.wpdd-report-section h2 {
|
||||
margin-bottom: 15px;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
@media (max-width: 1200px) {
|
||||
.wpdd-reports-tables {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
/* Settings Page */
|
||||
.wpdd-settings-sidebar {
|
||||
float: right;
|
||||
width: 300px;
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
.wpdd-settings-box {
|
||||
background: white;
|
||||
border: 1px solid #ccd0d4;
|
||||
padding: 20px;
|
||||
margin-bottom: 20px;
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 1px 3px rgba(0,0,0,0.05);
|
||||
}
|
||||
|
||||
.wpdd-settings-box h3 {
|
||||
margin-top: 0;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.wpdd-settings-box code {
|
||||
background: #f1f1f1;
|
||||
padding: 2px 5px;
|
||||
font-size: 12px;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.wpdd-settings-box ul {
|
||||
margin: 0;
|
||||
padding-left: 20px;
|
||||
}
|
||||
|
||||
.wpdd-settings-box li {
|
||||
margin-bottom: 8px;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.wpdd-status-good {
|
||||
color: #46b450;
|
||||
}
|
||||
|
||||
.wpdd-status-warning {
|
||||
color: #ffb900;
|
||||
}
|
||||
|
||||
.wpdd-status-error {
|
||||
color: #dc3232;
|
||||
}
|
||||
|
||||
#wpforms-settings .form-table {
|
||||
max-width: calc(100% - 340px);
|
||||
}
|
||||
|
||||
@media (max-width: 1200px) {
|
||||
.wpdd-settings-sidebar {
|
||||
float: none;
|
||||
width: 100%;
|
||||
margin-left: 0;
|
||||
margin-top: 30px;
|
||||
}
|
||||
|
||||
#wpforms-settings .form-table {
|
||||
max-width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
/* Responsive adjustments */
|
||||
@media (max-width: 782px) {
|
||||
.wpdd-file-header {
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.wpdd-file-url {
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.wpdd-settings-sidebar {
|
||||
width: 100%;
|
||||
margin-left: 0;
|
||||
margin-top: 20px;
|
||||
float: none;
|
||||
}
|
||||
|
||||
.wpdd-stats-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
/* Loading states */
|
||||
.wpdd-loading {
|
||||
position: relative;
|
||||
pointer-events: none;
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
.wpdd-loading::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
margin: -10px 0 0 -10px;
|
||||
border: 2px solid #ccc;
|
||||
border-top: 2px solid #0073aa;
|
||||
border-radius: 50%;
|
||||
animation: wpdd-spin 1s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes wpdd-spin {
|
||||
0% { transform: rotate(0deg); }
|
||||
100% { transform: rotate(360deg); }
|
||||
}
|
469
assets/css/frontend.css
Normal file
469
assets/css/frontend.css
Normal file
@@ -0,0 +1,469 @@
|
||||
/* WP Digital Download - Frontend Styles */
|
||||
|
||||
/* Shop Grid */
|
||||
.wpdd-shop-container {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.wpdd-shop-filters {
|
||||
background: #f8f9fa;
|
||||
padding: 20px;
|
||||
border-radius: 8px;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.wpdd-filter-form {
|
||||
display: flex;
|
||||
gap: 15px;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.wpdd-filter-form input[type="text"],
|
||||
.wpdd-filter-form select {
|
||||
padding: 8px 12px;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 4px;
|
||||
min-width: 150px;
|
||||
}
|
||||
|
||||
.wpdd-filter-submit {
|
||||
padding: 8px 16px;
|
||||
background: #0073aa;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
transition: background 0.3s;
|
||||
}
|
||||
|
||||
.wpdd-filter-submit:hover {
|
||||
background: #005a87;
|
||||
}
|
||||
|
||||
.wpdd-products-grid {
|
||||
display: grid;
|
||||
gap: 30px;
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
|
||||
.wpdd-columns-1 { grid-template-columns: 1fr; }
|
||||
.wpdd-columns-2 { grid-template-columns: repeat(2, 1fr); }
|
||||
.wpdd-columns-3 { grid-template-columns: repeat(3, 1fr); }
|
||||
.wpdd-columns-4 { grid-template-columns: repeat(4, 1fr); }
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.wpdd-columns-2,
|
||||
.wpdd-columns-3,
|
||||
.wpdd-columns-4 {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 769px) and (max-width: 1024px) {
|
||||
.wpdd-columns-3,
|
||||
.wpdd-columns-4 {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
}
|
||||
}
|
||||
|
||||
/* Product Cards */
|
||||
.wpdd-product-card {
|
||||
background: white;
|
||||
border: 1px solid #e1e5e9;
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
transition: transform 0.3s, box-shadow 0.3s;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.wpdd-product-card:hover {
|
||||
transform: translateY(-5px);
|
||||
box-shadow: 0 8px 25px rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
.wpdd-product-image {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
height: 200px;
|
||||
}
|
||||
|
||||
.wpdd-product-image img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
transition: transform 0.3s;
|
||||
}
|
||||
|
||||
.wpdd-product-card:hover .wpdd-product-image img {
|
||||
transform: scale(1.05);
|
||||
}
|
||||
|
||||
.wpdd-product-info {
|
||||
padding: 20px;
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.wpdd-product-title {
|
||||
margin: 0 0 10px 0;
|
||||
font-size: 18px;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.wpdd-product-title a {
|
||||
color: #333;
|
||||
text-decoration: none;
|
||||
transition: color 0.3s;
|
||||
}
|
||||
|
||||
.wpdd-product-title a:hover {
|
||||
color: #0073aa;
|
||||
}
|
||||
|
||||
.wpdd-product-meta {
|
||||
color: #666;
|
||||
font-size: 14px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.wpdd-product-creator {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.wpdd-product-excerpt {
|
||||
color: #555;
|
||||
font-size: 14px;
|
||||
line-height: 1.5;
|
||||
margin-bottom: 15px;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.wpdd-product-price {
|
||||
margin-bottom: 15px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.wpdd-price-free {
|
||||
color: #28a745;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.wpdd-price-regular {
|
||||
color: #333;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.wpdd-price-sale {
|
||||
color: #dc3545;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.wpdd-price-strike {
|
||||
text-decoration: line-through;
|
||||
color: #999;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.wpdd-product-actions {
|
||||
margin-top: auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.wpdd-product-actions .wpdd-btn {
|
||||
width: 100%;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
/* Buttons */
|
||||
.wpdd-btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 10px 20px;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
text-decoration: none;
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s;
|
||||
font-size: 14px;
|
||||
line-height: 1.4;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.wpdd-btn-primary {
|
||||
background: #0073aa;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.wpdd-btn-primary:hover {
|
||||
background: #005a87;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.wpdd-btn-view {
|
||||
background: #f8f9fa;
|
||||
color: #333;
|
||||
border: 1px solid #dee2e6;
|
||||
}
|
||||
|
||||
.wpdd-btn-view:hover {
|
||||
background: #e9ecef;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.wpdd-btn-buy {
|
||||
background: #28a745;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.wpdd-btn-buy:hover {
|
||||
background: #218838;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.wpdd-owned-product {
|
||||
background: #17a2b8 !important;
|
||||
color: white !important;
|
||||
padding: 10px 30px !important;
|
||||
}
|
||||
|
||||
.wpdd-owned-product:hover {
|
||||
background: #138496 !important;
|
||||
color: white !important;
|
||||
}
|
||||
|
||||
.wpdd-btn-view:hover {
|
||||
background: #e9ecef;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.wpdd-btn-download {
|
||||
background: #28a745;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.wpdd-btn-download:hover {
|
||||
background: #218838;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.wpdd-btn-large {
|
||||
padding: 15px 30px;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
/* Customer Purchases */
|
||||
.wpdd-customer-purchases {
|
||||
max-width: 1000px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.wpdd-purchases-table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
margin-bottom: 30px;
|
||||
background: white;
|
||||
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
.wpdd-purchases-table th,
|
||||
.wpdd-purchases-table td {
|
||||
padding: 15px;
|
||||
text-align: left;
|
||||
border-bottom: 1px solid #e1e5e9;
|
||||
}
|
||||
|
||||
.wpdd-purchases-table th {
|
||||
background: #f8f9fa;
|
||||
font-weight: 600;
|
||||
color: #495057;
|
||||
}
|
||||
|
||||
.wpdd-purchases-table tr:hover {
|
||||
background: #f8f9fa;
|
||||
}
|
||||
|
||||
.wpdd-download-expired {
|
||||
color: #dc3545;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
/* Checkout */
|
||||
.wpdd-checkout {
|
||||
max-width: 600px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.wpdd-checkout-product {
|
||||
background: #f8f9fa;
|
||||
padding: 20px;
|
||||
border-radius: 8px;
|
||||
margin-bottom: 30px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.wpdd-checkout-product h3 {
|
||||
margin: 0 0 15px 0;
|
||||
}
|
||||
|
||||
.wpdd-checkout-product img {
|
||||
max-width: 150px;
|
||||
height: auto;
|
||||
border-radius: 4px;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.wpdd-checkout-price {
|
||||
font-size: 24px;
|
||||
font-weight: bold;
|
||||
color: #0073aa;
|
||||
}
|
||||
|
||||
.wpdd-checkout-section {
|
||||
background: white;
|
||||
padding: 25px;
|
||||
border: 1px solid #e1e5e9;
|
||||
border-radius: 8px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.wpdd-checkout-section h4 {
|
||||
margin: 0 0 20px 0;
|
||||
padding-bottom: 10px;
|
||||
border-bottom: 1px solid #e1e5e9;
|
||||
}
|
||||
|
||||
.wpdd-checkout-section p {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.wpdd-checkout-section label {
|
||||
display: block;
|
||||
margin-bottom: 5px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.wpdd-checkout-section input[type="text"],
|
||||
.wpdd-checkout-section input[type="email"] {
|
||||
width: 100%;
|
||||
padding: 10px;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 4px;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.wpdd-checkout-section input[type="checkbox"] {
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
/* Thank You Page */
|
||||
.wpdd-thank-you {
|
||||
max-width: 600px;
|
||||
margin: 0 auto;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.wpdd-order-details {
|
||||
background: white;
|
||||
padding: 30px;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 4px 6px rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
.wpdd-order-info {
|
||||
background: #f8f9fa;
|
||||
padding: 20px;
|
||||
border-radius: 6px;
|
||||
margin: 20px 0;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.wpdd-download-section {
|
||||
margin: 30px 0;
|
||||
}
|
||||
|
||||
.wpdd-download-section h3 {
|
||||
color: #28a745;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
/* Pagination */
|
||||
.wpdd-pagination {
|
||||
text-align: center;
|
||||
margin: 40px 0;
|
||||
}
|
||||
|
||||
.wpdd-pagination .page-numbers {
|
||||
display: inline-block;
|
||||
padding: 8px 12px;
|
||||
margin: 0 4px;
|
||||
text-decoration: none;
|
||||
border: 1px solid #dee2e6;
|
||||
color: #495057;
|
||||
border-radius: 4px;
|
||||
transition: all 0.3s;
|
||||
}
|
||||
|
||||
.wpdd-pagination .page-numbers:hover,
|
||||
.wpdd-pagination .page-numbers.current {
|
||||
background: #0073aa;
|
||||
color: white;
|
||||
border-color: #0073aa;
|
||||
}
|
||||
|
||||
/* Responsive */
|
||||
@media (max-width: 768px) {
|
||||
.wpdd-shop-filters .wpdd-filter-form {
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
.wpdd-filter-form input,
|
||||
.wpdd-filter-form select {
|
||||
min-width: auto;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.wpdd-purchases-table {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.wpdd-purchases-table th,
|
||||
.wpdd-purchases-table td {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.wpdd-checkout-section {
|
||||
padding: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
/* No products message */
|
||||
.wpdd-no-products {
|
||||
text-align: center;
|
||||
color: #666;
|
||||
font-size: 18px;
|
||||
margin: 50px 0;
|
||||
}
|
||||
|
||||
/* Login required message */
|
||||
.wpdd-login-required {
|
||||
background: #fff3cd;
|
||||
color: #856404;
|
||||
padding: 15px;
|
||||
border-radius: 4px;
|
||||
border: 1px solid #ffeaa7;
|
||||
}
|
||||
|
||||
.wpdd-login-required a {
|
||||
color: #856404;
|
||||
font-weight: bold;
|
||||
}
|
411
assets/js/admin.js
Normal file
411
assets/js/admin.js
Normal file
@@ -0,0 +1,411 @@
|
||||
jQuery(document).ready(function($) {
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Main WPDD Admin Object
|
||||
*/
|
||||
window.WPDD_Admin = {
|
||||
|
||||
init: function() {
|
||||
this.initFileManager();
|
||||
this.initPriceToggle();
|
||||
this.initFormValidation();
|
||||
},
|
||||
|
||||
initFileManager: function() {
|
||||
var fileIndex = $('#wpdd-files-list .wpdd-file-item').length;
|
||||
|
||||
// Add new file
|
||||
$('#wpdd-add-file').on('click', function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
var template = $('#wpdd-file-template').html();
|
||||
template = template.replace(/INDEX/g, fileIndex);
|
||||
|
||||
var $newFile = $(template);
|
||||
$newFile.attr('data-index', fileIndex);
|
||||
|
||||
$('#wpdd-files-list').append($newFile);
|
||||
fileIndex++;
|
||||
|
||||
WPDD_Admin.updateFileIndices();
|
||||
});
|
||||
|
||||
// Remove file
|
||||
$(document).on('click', '.wpdd-remove-file', function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
if (confirm('Are you sure you want to remove this file?')) {
|
||||
$(this).closest('.wpdd-file-item').remove();
|
||||
WPDD_Admin.updateFileIndices();
|
||||
}
|
||||
});
|
||||
|
||||
// Upload file
|
||||
$(document).on('click', '.wpdd-upload-file', function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
var $button = $(this);
|
||||
var $container = $button.closest('.wpdd-file-item');
|
||||
var $urlInput = $container.find('.wpdd-file-url-input');
|
||||
var $idInput = $container.find('.wpdd-file-id');
|
||||
var $nameInput = $container.find('input[name*="[name]"]');
|
||||
|
||||
// Create file input element
|
||||
var $fileInput = $('<input type="file" style="display:none;" />');
|
||||
|
||||
$fileInput.on('change', function(event) {
|
||||
var file = event.target.files[0];
|
||||
if (!file) return;
|
||||
|
||||
// Show loading state
|
||||
$button.prop('disabled', true).text('Uploading...');
|
||||
|
||||
var formData = new FormData();
|
||||
formData.append('action', 'wpdd_upload_protected_file');
|
||||
formData.append('file', file);
|
||||
formData.append('nonce', wpdd_admin_nonce);
|
||||
|
||||
$.ajax({
|
||||
url: ajaxurl,
|
||||
type: 'POST',
|
||||
data: formData,
|
||||
processData: false,
|
||||
contentType: false,
|
||||
success: function(response) {
|
||||
if (response.success) {
|
||||
$urlInput.val(response.data.protected_url);
|
||||
$idInput.val(response.data.file_id);
|
||||
|
||||
if (!$nameInput.val()) {
|
||||
$nameInput.val(file.name);
|
||||
}
|
||||
|
||||
WPDD_Admin.showAdminNotice('File uploaded to protected directory', 'success');
|
||||
} else {
|
||||
WPDD_Admin.showAdminNotice(response.data || 'Upload failed', 'error');
|
||||
}
|
||||
|
||||
$button.prop('disabled', false).text('Upload File');
|
||||
},
|
||||
error: function() {
|
||||
WPDD_Admin.showAdminNotice('Upload failed', 'error');
|
||||
$button.prop('disabled', false).text('Upload File');
|
||||
}
|
||||
});
|
||||
|
||||
// Clean up
|
||||
$fileInput.remove();
|
||||
});
|
||||
|
||||
// Trigger file selection
|
||||
$('body').append($fileInput);
|
||||
$fileInput.trigger('click');
|
||||
});
|
||||
|
||||
// Make files sortable
|
||||
if ($.fn.sortable) {
|
||||
$('#wpdd-files-list').sortable({
|
||||
handle: '.wpdd-file-handle',
|
||||
placeholder: 'wpdd-file-placeholder',
|
||||
update: function() {
|
||||
WPDD_Admin.updateFileIndices();
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
moveToProtectedDirectory: function(attachmentId, $container) {
|
||||
$.ajax({
|
||||
url: ajaxurl,
|
||||
type: 'POST',
|
||||
data: {
|
||||
action: 'wpdd_move_to_protected',
|
||||
attachment_id: attachmentId,
|
||||
nonce: wpdd_admin_nonce
|
||||
},
|
||||
success: function(response) {
|
||||
if (response.success && response.data.protected_url) {
|
||||
$container.find('.wpdd-file-url-input').val(response.data.protected_url);
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
updateFileIndices: function() {
|
||||
$('#wpdd-files-list .wpdd-file-item').each(function(index) {
|
||||
var $item = $(this);
|
||||
$item.attr('data-index', index);
|
||||
|
||||
// Update input names
|
||||
$item.find('input').each(function() {
|
||||
var name = $(this).attr('name');
|
||||
if (name) {
|
||||
name = name.replace(/\[\d+\]/, '[' + index + ']');
|
||||
$(this).attr('name', name);
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
initPriceToggle: function() {
|
||||
$('#wpdd_is_free').on('change', function() {
|
||||
var $priceFields = $('.wpdd-price-field');
|
||||
if ($(this).is(':checked')) {
|
||||
$priceFields.slideUp();
|
||||
} else {
|
||||
$priceFields.slideDown();
|
||||
}
|
||||
}).trigger('change');
|
||||
},
|
||||
|
||||
initFormValidation: function() {
|
||||
// Validate PayPal settings
|
||||
$('input[name="wpdd_paypal_client_id"], input[name="wpdd_paypal_secret"]').on('blur', function() {
|
||||
var $field = $(this);
|
||||
var value = $field.val().trim();
|
||||
|
||||
if (value && value.length < 10) {
|
||||
$field.addClass('error');
|
||||
WPDD_Admin.showAdminNotice('Invalid PayPal credential format', 'error');
|
||||
} else {
|
||||
$field.removeClass('error');
|
||||
}
|
||||
});
|
||||
|
||||
// Validate email fields
|
||||
$('input[type="email"]').on('blur', function() {
|
||||
var $field = $(this);
|
||||
var value = $field.val().trim();
|
||||
var emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
||||
|
||||
if (value && !emailRegex.test(value)) {
|
||||
$field.addClass('error');
|
||||
} else {
|
||||
$field.removeClass('error');
|
||||
}
|
||||
});
|
||||
|
||||
// Validate number fields
|
||||
$('input[type="number"]').on('input', function() {
|
||||
var $field = $(this);
|
||||
var value = parseFloat($field.val());
|
||||
var min = parseFloat($field.attr('min'));
|
||||
var max = parseFloat($field.attr('max'));
|
||||
|
||||
if (isNaN(value) || (min !== undefined && value < min) || (max !== undefined && value > max)) {
|
||||
$field.addClass('error');
|
||||
} else {
|
||||
$field.removeClass('error');
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
showAdminNotice: function(message, type) {
|
||||
type = type || 'info';
|
||||
|
||||
var notice = $('<div class="notice notice-' + type + ' is-dismissible">' +
|
||||
'<p>' + message + '</p>' +
|
||||
'<button type="button" class="notice-dismiss"></button>' +
|
||||
'</div>');
|
||||
|
||||
$('.wrap h1').first().after(notice);
|
||||
|
||||
// Handle dismiss
|
||||
notice.find('.notice-dismiss').on('click', function() {
|
||||
notice.fadeOut(function() {
|
||||
notice.remove();
|
||||
});
|
||||
});
|
||||
|
||||
// Auto-dismiss after 5 seconds for non-error notices
|
||||
if (type !== 'error') {
|
||||
setTimeout(function() {
|
||||
notice.fadeOut(function() {
|
||||
notice.remove();
|
||||
});
|
||||
}, 5000);
|
||||
}
|
||||
},
|
||||
|
||||
initReportsCharts: function() {
|
||||
// Placeholder for future chart implementation
|
||||
// Could integrate Chart.js or similar library
|
||||
},
|
||||
|
||||
initBulkActions: function() {
|
||||
// Handle bulk actions for orders, customers, etc.
|
||||
$('.bulkactions select').on('change', function() {
|
||||
var action = $(this).val();
|
||||
var $button = $(this).siblings('input[type="submit"]');
|
||||
|
||||
if (action) {
|
||||
$button.prop('disabled', false);
|
||||
} else {
|
||||
$button.prop('disabled', true);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
initQuickEdit: function() {
|
||||
// Quick edit functionality for products
|
||||
$('.editinline').on('click', function() {
|
||||
var $row = $(this).closest('tr');
|
||||
var productId = $row.find('.check-column input').val();
|
||||
|
||||
// Populate quick edit fields with current values
|
||||
setTimeout(function() {
|
||||
var $quickEdit = $('.inline-edit-row');
|
||||
|
||||
// Pre-fill price from the displayed value
|
||||
var price = $row.find('.column-wpdd_price').text().replace('$', '');
|
||||
if (price !== 'Free') {
|
||||
$quickEdit.find('input[name="_wpdd_price"]').val(price);
|
||||
}
|
||||
|
||||
}, 100);
|
||||
});
|
||||
},
|
||||
|
||||
initFilePreview: function() {
|
||||
// Show file preview/details when hovering over file names
|
||||
$(document).on('mouseenter', '.wpdd-file-url-input', function() {
|
||||
var url = $(this).val();
|
||||
if (url) {
|
||||
var filename = url.split('/').pop();
|
||||
var extension = filename.split('.').pop().toLowerCase();
|
||||
var fileType = WPDD_Admin.getFileType(extension);
|
||||
|
||||
$(this).attr('title', 'File: ' + filename + ' (Type: ' + fileType + ')');
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
getFileType: function(extension) {
|
||||
var types = {
|
||||
'pdf': 'PDF Document',
|
||||
'doc': 'Word Document',
|
||||
'docx': 'Word Document',
|
||||
'zip': 'Archive',
|
||||
'rar': 'Archive',
|
||||
'jpg': 'Image',
|
||||
'jpeg': 'Image',
|
||||
'png': 'Image',
|
||||
'gif': 'Image',
|
||||
'mp3': 'Audio',
|
||||
'wav': 'Audio',
|
||||
'mp4': 'Video',
|
||||
'avi': 'Video'
|
||||
};
|
||||
|
||||
return types[extension] || 'File';
|
||||
},
|
||||
|
||||
initColorPicker: function() {
|
||||
// Initialize color picker for watermark settings
|
||||
if ($.fn.wpColorPicker) {
|
||||
$('.wpdd-color-picker').wpColorPicker();
|
||||
}
|
||||
},
|
||||
|
||||
initTabs: function() {
|
||||
// Settings page tabs
|
||||
$('.wpdd-settings-tabs').on('click', 'a', function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
var $tab = $(this);
|
||||
var target = $tab.attr('href');
|
||||
|
||||
// Update active tab
|
||||
$tab.siblings().removeClass('nav-tab-active');
|
||||
$tab.addClass('nav-tab-active');
|
||||
|
||||
// Show/hide content
|
||||
$('.wpdd-settings-content').hide();
|
||||
$(target).show();
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// Initialize admin functionality
|
||||
WPDD_Admin.init();
|
||||
|
||||
// Add admin-specific styles
|
||||
$('<style>')
|
||||
.prop('type', 'text/css')
|
||||
.html(`
|
||||
.wpdd-file-item.ui-sortable-helper {
|
||||
box-shadow: 0 4px 8px rgba(0,0,0,0.2);
|
||||
transform: rotate(2deg);
|
||||
}
|
||||
|
||||
.wpdd-file-placeholder {
|
||||
border: 2px dashed #0073aa !important;
|
||||
background: transparent !important;
|
||||
height: 80px !important;
|
||||
}
|
||||
|
||||
input.error {
|
||||
border-color: #dc3232 !important;
|
||||
box-shadow: 0 0 2px rgba(220, 50, 50, 0.3) !important;
|
||||
}
|
||||
|
||||
.wpdd-loading-overlay {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: rgba(255,255,255,0.8);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
z-index: 9999;
|
||||
}
|
||||
|
||||
.wpdd-spinner {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border: 4px solid #f3f3f3;
|
||||
border-top: 4px solid #0073aa;
|
||||
border-radius: 50%;
|
||||
animation: spin 1s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
0% { transform: rotate(0deg); }
|
||||
100% { transform: rotate(360deg); }
|
||||
}
|
||||
|
||||
.wpdd-help-tip {
|
||||
color: #666;
|
||||
cursor: help;
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
.wpdd-help-tip:hover {
|
||||
color: #0073aa;
|
||||
}
|
||||
`)
|
||||
.appendTo('head');
|
||||
|
||||
// Initialize additional features based on current page
|
||||
var currentScreen = window.pagenow || '';
|
||||
|
||||
if (currentScreen === 'wpdd_product') {
|
||||
WPDD_Admin.initQuickEdit();
|
||||
WPDD_Admin.initFilePreview();
|
||||
}
|
||||
|
||||
if (currentScreen.includes('wpdd-settings')) {
|
||||
WPDD_Admin.initColorPicker();
|
||||
WPDD_Admin.initTabs();
|
||||
}
|
||||
|
||||
if (currentScreen.includes('wpdd-reports')) {
|
||||
WPDD_Admin.initReportsCharts();
|
||||
}
|
||||
|
||||
// Global admin features
|
||||
WPDD_Admin.initBulkActions();
|
||||
});
|
554
assets/js/frontend.js
Normal file
554
assets/js/frontend.js
Normal file
@@ -0,0 +1,554 @@
|
||||
jQuery(document).ready(function($) {
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Main WPDD Frontend Object
|
||||
*/
|
||||
window.WPDD = {
|
||||
|
||||
init: function() {
|
||||
this.bindEvents();
|
||||
this.initProductCards();
|
||||
this.initCheckout();
|
||||
},
|
||||
|
||||
bindEvents: function() {
|
||||
// Add to cart buttons
|
||||
$(document).on('click', '.wpdd-add-to-cart', this.addToCart);
|
||||
|
||||
// Free download buttons
|
||||
$(document).on('click', '.wpdd-free-download', this.processFreeDownload);
|
||||
|
||||
// Product quickview
|
||||
$(document).on('click', '.wpdd-quickview', this.showQuickview);
|
||||
|
||||
// Filter form submission
|
||||
$(document).on('submit', '.wpdd-filter-form', this.handleFilters);
|
||||
|
||||
// Download status check
|
||||
$(document).on('click', '.wpdd-check-download', this.checkDownloadStatus);
|
||||
},
|
||||
|
||||
initProductCards: function() {
|
||||
// Add hover effects and animations
|
||||
$('.wpdd-product-card').each(function() {
|
||||
var $card = $(this);
|
||||
var $image = $card.find('.wpdd-product-image img');
|
||||
|
||||
$card.hover(
|
||||
function() {
|
||||
$(this).addClass('hovered');
|
||||
},
|
||||
function() {
|
||||
$(this).removeClass('hovered');
|
||||
}
|
||||
);
|
||||
});
|
||||
},
|
||||
|
||||
initCheckout: function() {
|
||||
// Free product checkout handler
|
||||
$('#wpdd-checkout-form').on('submit', function(e) {
|
||||
var $form = $(this);
|
||||
var isFree = $form.data('product-free') == '1';
|
||||
|
||||
if (isFree) {
|
||||
e.preventDefault();
|
||||
WPDD.processFreeCheckout($form);
|
||||
}
|
||||
});
|
||||
|
||||
// Price display toggle based on free checkbox
|
||||
$('#wpdd_is_free').on('change', function() {
|
||||
var $priceFields = $('.wpdd-price-field');
|
||||
if ($(this).is(':checked')) {
|
||||
$priceFields.hide();
|
||||
} else {
|
||||
$priceFields.show();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
addToCart: function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
var $button = $(this);
|
||||
var productId = $button.data('product-id');
|
||||
|
||||
if (!productId) {
|
||||
WPDD.showNotice('Invalid product', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
$button.addClass('loading').prop('disabled', true);
|
||||
|
||||
$.ajax({
|
||||
url: wpdd_ajax.url,
|
||||
type: 'POST',
|
||||
data: {
|
||||
action: 'wpdd_add_to_cart',
|
||||
product_id: productId,
|
||||
nonce: wpdd_ajax.nonce
|
||||
},
|
||||
success: function(response) {
|
||||
if (response.success) {
|
||||
WPDD.showNotice(response.data.message, 'success');
|
||||
|
||||
// Update cart count if element exists
|
||||
$('.wpdd-cart-count').text(response.data.cart_count);
|
||||
|
||||
// Show checkout button
|
||||
if (response.data.checkout_url) {
|
||||
$button.after('<a href="' + response.data.checkout_url +
|
||||
'" class="wpdd-btn wpdd-btn-primary">Checkout</a>');
|
||||
}
|
||||
} else {
|
||||
WPDD.showNotice(response.data, 'error');
|
||||
}
|
||||
},
|
||||
error: function() {
|
||||
WPDD.showNotice('An error occurred. Please try again.', 'error');
|
||||
},
|
||||
complete: function() {
|
||||
$button.removeClass('loading').prop('disabled', false);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
processFreeDownload: function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
var $button = $(this);
|
||||
var productId = $button.data('product-id');
|
||||
var $form = $button.closest('form');
|
||||
|
||||
if (!productId) {
|
||||
WPDD.showNotice('Invalid product', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
var customerEmail = $form.find('input[name="customer_email"]').val();
|
||||
var customerName = $form.find('input[name="customer_name"]').val();
|
||||
|
||||
if (!customerEmail && !WPDD.isUserLoggedIn()) {
|
||||
WPDD.showNotice('Please provide your email address', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
$button.addClass('loading').prop('disabled', true);
|
||||
|
||||
$.ajax({
|
||||
url: wpdd_ajax.url,
|
||||
type: 'POST',
|
||||
data: {
|
||||
action: 'wpdd_process_free_download',
|
||||
product_id: productId,
|
||||
customer_email: customerEmail,
|
||||
customer_name: customerName,
|
||||
nonce: wpdd_ajax.nonce
|
||||
},
|
||||
success: function(response) {
|
||||
if (response.success) {
|
||||
window.location.href = response.data.redirect_url;
|
||||
} else {
|
||||
WPDD.showNotice(response.data, 'error');
|
||||
}
|
||||
},
|
||||
error: function() {
|
||||
WPDD.showNotice('An error occurred. Please try again.', 'error');
|
||||
},
|
||||
complete: function() {
|
||||
$button.removeClass('loading').prop('disabled', false);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
processFreeCheckout: function($form) {
|
||||
var formData = $form.serialize();
|
||||
var $submitBtn = $form.find('button[type="submit"]');
|
||||
var productId = $form.find('input[name="product_id"]').val();
|
||||
|
||||
$submitBtn.addClass('loading').prop('disabled', true);
|
||||
|
||||
// Add visual feedback
|
||||
$submitBtn.text('Processing...');
|
||||
|
||||
$.ajax({
|
||||
url: wpdd_ajax.url,
|
||||
type: 'POST',
|
||||
data: formData + '&action=wpdd_process_free_download&nonce=' + wpdd_ajax.nonce + '&product_id=' + productId,
|
||||
success: function(response) {
|
||||
if (response.success) {
|
||||
window.location.href = response.data.redirect_url;
|
||||
} else {
|
||||
WPDD.showNotice(response.data || 'Failed to process download', 'error');
|
||||
$submitBtn.text('Get Free Download');
|
||||
}
|
||||
},
|
||||
error: function(xhr, status, error) {
|
||||
console.error('AJAX Error:', status, error);
|
||||
WPDD.showNotice('An error occurred. Please try again.', 'error');
|
||||
$submitBtn.text('Get Free Download');
|
||||
},
|
||||
complete: function() {
|
||||
$submitBtn.removeClass('loading').prop('disabled', false);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
showQuickview: function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
var productId = $(this).data('product-id');
|
||||
|
||||
if (!productId) {
|
||||
return;
|
||||
}
|
||||
|
||||
$.ajax({
|
||||
url: wpdd_ajax.url,
|
||||
type: 'POST',
|
||||
data: {
|
||||
action: 'wpdd_get_product_details',
|
||||
product_id: productId,
|
||||
nonce: wpdd_ajax.nonce
|
||||
},
|
||||
success: function(response) {
|
||||
if (response.success) {
|
||||
WPDD.displayQuickview(response.data);
|
||||
} else {
|
||||
WPDD.showNotice('Unable to load product details', 'error');
|
||||
}
|
||||
},
|
||||
error: function() {
|
||||
WPDD.showNotice('An error occurred. Please try again.', 'error');
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
displayQuickview: function(product) {
|
||||
var modal = $('<div class="wpdd-modal"><div class="wpdd-modal-content"></div></div>');
|
||||
var content = '';
|
||||
|
||||
content += '<div class="wpdd-modal-header">';
|
||||
content += '<h2>' + product.title + '</h2>';
|
||||
content += '<button class="wpdd-modal-close">×</button>';
|
||||
content += '</div>';
|
||||
|
||||
content += '<div class="wpdd-modal-body">';
|
||||
if (product.thumbnail) {
|
||||
content += '<img src="' + product.thumbnail + '" alt="' + product.title + '" class="wpdd-modal-image">';
|
||||
}
|
||||
content += '<div class="wpdd-modal-details">';
|
||||
content += '<p class="wpdd-modal-price">';
|
||||
if (product.is_free) {
|
||||
content += '<span class="wpdd-price-free">Free</span>';
|
||||
} else {
|
||||
content += '<span class="wpdd-price-regular">$' + product.final_price + '</span>';
|
||||
}
|
||||
content += '</p>';
|
||||
content += '<p class="wpdd-modal-creator">by ' + product.creator.name + '</p>';
|
||||
content += '<div class="wpdd-modal-description">' + product.description + '</div>';
|
||||
content += '<p><strong>Files:</strong> ' + product.files_count + '</p>';
|
||||
content += '<p><strong>Download Limit:</strong> ' + product.download_limit + '</p>';
|
||||
content += '<p><strong>Expires:</strong> ' + product.download_expiry + '</p>';
|
||||
content += '</div>';
|
||||
content += '</div>';
|
||||
|
||||
content += '<div class="wpdd-modal-footer">';
|
||||
content += '<a href="' + window.location.origin + '?product_id=' + product.id +
|
||||
'" class="wpdd-btn wpdd-btn-primary">View Details</a>';
|
||||
content += '</div>';
|
||||
|
||||
modal.find('.wpdd-modal-content').html(content);
|
||||
$('body').append(modal);
|
||||
|
||||
modal.addClass('active');
|
||||
|
||||
// Close modal events
|
||||
modal.on('click', '.wpdd-modal-close, .wpdd-modal', function(e) {
|
||||
if (e.target === this) {
|
||||
modal.removeClass('active');
|
||||
setTimeout(function() {
|
||||
modal.remove();
|
||||
}, 300);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
handleFilters: function(e) {
|
||||
// Let the form submit naturally for now
|
||||
// Could be enhanced with AJAX filtering
|
||||
},
|
||||
|
||||
checkDownloadStatus: function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
var productId = $(this).data('product-id');
|
||||
var $button = $(this);
|
||||
|
||||
if (!WPDD.isUserLoggedIn()) {
|
||||
WPDD.showNotice('Please login to check download status', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
$button.addClass('loading');
|
||||
|
||||
$.ajax({
|
||||
url: wpdd_ajax.url,
|
||||
type: 'POST',
|
||||
data: {
|
||||
action: 'wpdd_check_download_status',
|
||||
product_id: productId,
|
||||
nonce: wpdd_ajax.nonce
|
||||
},
|
||||
success: function(response) {
|
||||
if (response.success) {
|
||||
var data = response.data;
|
||||
if (data.can_download && data.download_url) {
|
||||
window.location.href = data.download_url;
|
||||
} else {
|
||||
WPDD.showNotice(data.message, data.can_download ? 'success' : 'error');
|
||||
}
|
||||
} else {
|
||||
WPDD.showNotice(response.data, 'error');
|
||||
}
|
||||
},
|
||||
error: function() {
|
||||
WPDD.showNotice('An error occurred. Please try again.', 'error');
|
||||
},
|
||||
complete: function() {
|
||||
$button.removeClass('loading');
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
showNotice: function(message, type) {
|
||||
type = type || 'info';
|
||||
|
||||
var notice = $('<div class="wpdd-notice wpdd-notice-' + type + '">' +
|
||||
'<p>' + message + '</p>' +
|
||||
'<button class="wpdd-notice-dismiss">×</button>' +
|
||||
'</div>');
|
||||
|
||||
$('body').prepend(notice);
|
||||
|
||||
notice.addClass('active');
|
||||
|
||||
// Auto-dismiss after 5 seconds
|
||||
setTimeout(function() {
|
||||
notice.removeClass('active');
|
||||
setTimeout(function() {
|
||||
notice.remove();
|
||||
}, 300);
|
||||
}, 5000);
|
||||
|
||||
// Manual dismiss
|
||||
notice.find('.wpdd-notice-dismiss').on('click', function() {
|
||||
notice.removeClass('active');
|
||||
setTimeout(function() {
|
||||
notice.remove();
|
||||
}, 300);
|
||||
});
|
||||
},
|
||||
|
||||
isUserLoggedIn: function() {
|
||||
return $('body').hasClass('logged-in');
|
||||
},
|
||||
|
||||
formatPrice: function(price) {
|
||||
return '$' + parseFloat(price).toFixed(2);
|
||||
}
|
||||
};
|
||||
|
||||
// Initialize frontend functionality
|
||||
WPDD.init();
|
||||
|
||||
// Add modal and notice styles if not already present
|
||||
if (!$('#wpdd-dynamic-styles').length) {
|
||||
var styles = `
|
||||
<style id="wpdd-dynamic-styles">
|
||||
.wpdd-modal {
|
||||
display: flex;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: rgba(0,0,0,0.8);
|
||||
z-index: 999999;
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
transition: all 0.3s;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.wpdd-modal.active {
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
.wpdd-modal-content {
|
||||
background: white;
|
||||
max-width: 600px;
|
||||
width: 90%;
|
||||
max-height: 80vh;
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
transform: scale(0.8);
|
||||
transition: transform 0.3s;
|
||||
}
|
||||
|
||||
.wpdd-modal.active .wpdd-modal-content {
|
||||
transform: scale(1);
|
||||
}
|
||||
|
||||
.wpdd-modal-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 20px;
|
||||
border-bottom: 1px solid #eee;
|
||||
}
|
||||
|
||||
.wpdd-modal-header h2 {
|
||||
margin: 0;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.wpdd-modal-close {
|
||||
background: none;
|
||||
border: none;
|
||||
font-size: 24px;
|
||||
cursor: pointer;
|
||||
color: #666;
|
||||
padding: 0;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.wpdd-modal-body {
|
||||
padding: 20px;
|
||||
max-height: 50vh;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.wpdd-modal-image {
|
||||
width: 100%;
|
||||
max-width: 200px;
|
||||
height: auto;
|
||||
float: left;
|
||||
margin: 0 20px 20px 0;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.wpdd-modal-footer {
|
||||
padding: 20px;
|
||||
border-top: 1px solid #eee;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.wpdd-notice {
|
||||
position: fixed;
|
||||
top: 32px;
|
||||
right: 20px;
|
||||
max-width: 400px;
|
||||
z-index: 999999;
|
||||
opacity: 0;
|
||||
transform: translateX(100%);
|
||||
transition: all 0.3s;
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 4px 6px rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
.wpdd-notice.active {
|
||||
opacity: 1;
|
||||
transform: translateX(0);
|
||||
}
|
||||
|
||||
.wpdd-notice p {
|
||||
margin: 0;
|
||||
padding: 15px 40px 15px 15px;
|
||||
}
|
||||
|
||||
.wpdd-notice-dismiss {
|
||||
position: absolute;
|
||||
top: 5px;
|
||||
right: 10px;
|
||||
background: none;
|
||||
border: none;
|
||||
font-size: 18px;
|
||||
cursor: pointer;
|
||||
color: inherit;
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
.wpdd-notice-success {
|
||||
background: #d4edda;
|
||||
color: #155724;
|
||||
border: 1px solid #c3e6cb;
|
||||
}
|
||||
|
||||
.wpdd-notice-error {
|
||||
background: #f8d7da;
|
||||
color: #721c24;
|
||||
border: 1px solid #f5c6cb;
|
||||
}
|
||||
|
||||
.wpdd-notice-info {
|
||||
background: #d1ecf1;
|
||||
color: #0c5460;
|
||||
border: 1px solid #bee5eb;
|
||||
}
|
||||
|
||||
.loading {
|
||||
position: relative;
|
||||
pointer-events: none;
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
.loading::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
margin: -8px 0 0 -8px;
|
||||
border: 2px solid transparent;
|
||||
border-top: 2px solid currentColor;
|
||||
border-radius: 50%;
|
||||
animation: spin 1s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
0% { transform: rotate(0deg); }
|
||||
100% { transform: rotate(360deg); }
|
||||
}
|
||||
|
||||
@media (max-width: 600px) {
|
||||
.wpdd-modal-content {
|
||||
width: 95%;
|
||||
}
|
||||
|
||||
.wpdd-modal-image {
|
||||
float: none;
|
||||
margin: 0 0 20px 0;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.wpdd-notice {
|
||||
right: 10px;
|
||||
left: 10px;
|
||||
max-width: none;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
`;
|
||||
$('head').append(styles);
|
||||
}
|
||||
});
|
346
assets/js/paypal.js
Normal file
346
assets/js/paypal.js
Normal file
@@ -0,0 +1,346 @@
|
||||
jQuery(document).ready(function($) {
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* PayPal Integration Object
|
||||
*/
|
||||
window.WPDD_PayPal = {
|
||||
|
||||
init: function() {
|
||||
if (typeof paypal !== 'undefined') {
|
||||
this.renderPayPalButton();
|
||||
}
|
||||
},
|
||||
|
||||
renderPayPalButton: function() {
|
||||
var $container = $('#wpdd-paypal-button');
|
||||
|
||||
if (!$container.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
var $form = $container.closest('form');
|
||||
|
||||
paypal.Buttons({
|
||||
createOrder: function(data, actions) {
|
||||
return WPDD_PayPal.createOrder($form);
|
||||
},
|
||||
|
||||
onApprove: function(data, actions) {
|
||||
return WPDD_PayPal.captureOrder(data.orderID);
|
||||
},
|
||||
|
||||
onError: function(err) {
|
||||
console.error('PayPal Error:', err);
|
||||
WPDD_PayPal.showError('Payment processing failed. Please try again.');
|
||||
},
|
||||
|
||||
onCancel: function(data) {
|
||||
WPDD_PayPal.showNotice('Payment was cancelled.', 'info');
|
||||
}
|
||||
|
||||
}).render('#wpdd-paypal-button');
|
||||
},
|
||||
|
||||
createOrder: function($form) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
var formData = $form.serialize();
|
||||
|
||||
$.ajax({
|
||||
url: wpdd_paypal.ajax_url,
|
||||
type: 'POST',
|
||||
data: formData + '&action=wpdd_create_paypal_order&nonce=' + wpdd_paypal.nonce,
|
||||
success: function(response) {
|
||||
if (response.success) {
|
||||
resolve(response.data.orderID);
|
||||
} else {
|
||||
reject(new Error(response.data || 'Failed to create PayPal order'));
|
||||
}
|
||||
},
|
||||
error: function(xhr, status, error) {
|
||||
reject(new Error('Network error: ' + error));
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
captureOrder: function(orderID) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
$.ajax({
|
||||
url: wpdd_paypal.ajax_url,
|
||||
type: 'POST',
|
||||
data: {
|
||||
action: 'wpdd_capture_paypal_order',
|
||||
orderID: orderID,
|
||||
nonce: wpdd_paypal.nonce
|
||||
},
|
||||
success: function(response) {
|
||||
if (response.success) {
|
||||
// Redirect to thank you page
|
||||
window.location.href = response.data.redirect_url;
|
||||
} else {
|
||||
reject(new Error(response.data || 'Failed to capture payment'));
|
||||
}
|
||||
},
|
||||
error: function(xhr, status, error) {
|
||||
reject(new Error('Network error: ' + error));
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
showError: function(message) {
|
||||
this.showNotice(message, 'error');
|
||||
},
|
||||
|
||||
showNotice: function(message, type) {
|
||||
type = type || 'info';
|
||||
|
||||
// Remove existing notices
|
||||
$('.wpdd-paypal-notice').remove();
|
||||
|
||||
var notice = $('<div class="wpdd-paypal-notice wpdd-notice-' + type + '">' +
|
||||
'<p>' + message + '</p>' +
|
||||
'<button class="wpdd-notice-dismiss">×</button>' +
|
||||
'</div>');
|
||||
|
||||
$('#wpdd-paypal-button').before(notice);
|
||||
|
||||
// Auto-dismiss after 5 seconds
|
||||
setTimeout(function() {
|
||||
notice.fadeOut(function() {
|
||||
notice.remove();
|
||||
});
|
||||
}, 5000);
|
||||
|
||||
// Manual dismiss
|
||||
notice.find('.wpdd-notice-dismiss').on('click', function() {
|
||||
notice.fadeOut(function() {
|
||||
notice.remove();
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
validateForm: function($form) {
|
||||
var isValid = true;
|
||||
var errors = [];
|
||||
|
||||
// Check required fields
|
||||
$form.find('input[required]').each(function() {
|
||||
var $field = $(this);
|
||||
var value = $field.val().trim();
|
||||
var fieldName = $field.attr('name') || $field.attr('id');
|
||||
|
||||
if (!value) {
|
||||
isValid = false;
|
||||
errors.push(fieldName + ' is required');
|
||||
$field.addClass('error');
|
||||
} else {
|
||||
$field.removeClass('error');
|
||||
}
|
||||
});
|
||||
|
||||
// Validate email format
|
||||
$form.find('input[type="email"]').each(function() {
|
||||
var $field = $(this);
|
||||
var value = $field.val().trim();
|
||||
var emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
||||
|
||||
if (value && !emailRegex.test(value)) {
|
||||
isValid = false;
|
||||
errors.push('Please enter a valid email address');
|
||||
$field.addClass('error');
|
||||
}
|
||||
});
|
||||
|
||||
if (!isValid) {
|
||||
this.showError(errors.join('<br>'));
|
||||
}
|
||||
|
||||
return isValid;
|
||||
},
|
||||
|
||||
showLoadingState: function() {
|
||||
$('#wpdd-paypal-button').addClass('wpdd-loading');
|
||||
},
|
||||
|
||||
hideLoadingState: function() {
|
||||
$('#wpdd-paypal-button').removeClass('wpdd-loading');
|
||||
},
|
||||
|
||||
disableForm: function($form) {
|
||||
$form.find('input, select, button').prop('disabled', true);
|
||||
},
|
||||
|
||||
enableForm: function($form) {
|
||||
$form.find('input, select, button').prop('disabled', false);
|
||||
}
|
||||
};
|
||||
|
||||
// Initialize PayPal integration after object definition
|
||||
WPDD_PayPal.init();
|
||||
|
||||
// Add PayPal-specific styles
|
||||
$('<style>')
|
||||
.prop('type', 'text/css')
|
||||
.html(`
|
||||
#wpdd-paypal-button {
|
||||
margin: 20px 0;
|
||||
min-height: 45px;
|
||||
}
|
||||
|
||||
.wpdd-paypal-notice {
|
||||
padding: 12px 16px;
|
||||
margin-bottom: 15px;
|
||||
border-radius: 4px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.wpdd-notice-success {
|
||||
background: #d4edda;
|
||||
color: #155724;
|
||||
border: 1px solid #c3e6cb;
|
||||
}
|
||||
|
||||
.wpdd-notice-error {
|
||||
background: #f8d7da;
|
||||
color: #721c24;
|
||||
border: 1px solid #f5c6cb;
|
||||
}
|
||||
|
||||
.wpdd-notice-info {
|
||||
background: #d1ecf1;
|
||||
color: #0c5460;
|
||||
border: 1px solid #bee5eb;
|
||||
}
|
||||
|
||||
.wpdd-notice-dismiss {
|
||||
position: absolute;
|
||||
top: 8px;
|
||||
right: 12px;
|
||||
background: none;
|
||||
border: none;
|
||||
font-size: 16px;
|
||||
cursor: pointer;
|
||||
color: inherit;
|
||||
opacity: 0.7;
|
||||
padding: 0;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.wpdd-notice-dismiss:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.wpdd-loading {
|
||||
position: relative;
|
||||
opacity: 0.6;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.wpdd-loading::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
margin: -10px 0 0 -10px;
|
||||
border: 2px solid #ccc;
|
||||
border-top: 2px solid #0073aa;
|
||||
border-radius: 50%;
|
||||
animation: wpdd-paypal-spin 1s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes wpdd-paypal-spin {
|
||||
0% { transform: rotate(0deg); }
|
||||
100% { transform: rotate(360deg); }
|
||||
}
|
||||
|
||||
input.error {
|
||||
border-color: #dc3545 !important;
|
||||
box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.25) !important;
|
||||
}
|
||||
|
||||
.wpdd-checkout-section {
|
||||
transition: opacity 0.3s;
|
||||
}
|
||||
|
||||
.wpdd-checkout-section.disabled {
|
||||
opacity: 0.5;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
/* PayPal button container responsive */
|
||||
@media (max-width: 400px) {
|
||||
#wpdd-paypal-button {
|
||||
min-height: 40px;
|
||||
}
|
||||
}
|
||||
|
||||
/* Form validation styling */
|
||||
.wpdd-form-row {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.wpdd-form-row.has-error input {
|
||||
border-color: #dc3545;
|
||||
}
|
||||
|
||||
.wpdd-field-error {
|
||||
color: #dc3545;
|
||||
font-size: 12px;
|
||||
margin-top: 5px;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.wpdd-form-row.has-error .wpdd-field-error {
|
||||
display: block;
|
||||
}
|
||||
`)
|
||||
.appendTo('head');
|
||||
|
||||
// Form validation enhancement
|
||||
$(document).on('blur', '#wpdd-checkout-form input[required]', function() {
|
||||
var $field = $(this);
|
||||
var $row = $field.closest('.wpdd-form-row');
|
||||
var value = $field.val().trim();
|
||||
|
||||
if (!value) {
|
||||
$row.addClass('has-error');
|
||||
} else {
|
||||
$row.removeClass('has-error');
|
||||
}
|
||||
});
|
||||
|
||||
// Real-time email validation
|
||||
$(document).on('input', '#wpdd-checkout-form input[type="email"]', function() {
|
||||
var $field = $(this);
|
||||
var $row = $field.closest('.wpdd-form-row');
|
||||
var value = $field.val().trim();
|
||||
var emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
||||
|
||||
if (value && !emailRegex.test(value)) {
|
||||
$row.addClass('has-error');
|
||||
} else {
|
||||
$row.removeClass('has-error');
|
||||
}
|
||||
});
|
||||
|
||||
// Prevent double-submission
|
||||
var formSubmitting = false;
|
||||
|
||||
$(document).on('submit', '#wpdd-checkout-form', function(e) {
|
||||
if (formSubmitting) {
|
||||
e.preventDefault();
|
||||
return false;
|
||||
}
|
||||
|
||||
formSubmitting = true;
|
||||
|
||||
// Re-enable after 5 seconds as failsafe
|
||||
setTimeout(function() {
|
||||
formSubmitting = false;
|
||||
}, 5000);
|
||||
});
|
||||
});
|
Reference in New Issue
Block a user