= "$year-10-15" && $now <= "$year-10-31" ) ) { return array( 'key' => 'halloween', 'discount' => 25, 'end_date' => "$year-10-31", 'coupon' => 'HALLOWEEN', 'widget_title' => __( 'Ultimate Cursor — Halloween Sale', 'ultimate-cursor' ), 'notice_title' => __( 'Halloween Sale — Ultimate Cursor Pro', 'ultimate-cursor' ), 'description' => __( 'Unlock spooky-good premium cursor effects, advanced customisation & priority support this Halloween!', 'ultimate-cursor' ), 'button_text' => __( 'Grab 25% OFF', 'ultimate-cursor' ), 'accent' => '#ff6600', 'accent_secondary' => '#a855f7', 'gradient' => 'linear-gradient(135deg, #1a0a2e 0%, #2d1150 35%, #4c1d95 70%, #7c3aed 100%)', 'icon' => 'pumpkin', 'features' => $features, ); } // Black Friday / Cyber Monday: November 1 – December 5. if ( $test_black_friday || ( $now >= "$year-11-01" && $now <= "$year-12-05" ) ) { return array( 'key' => 'black_friday', 'discount' => 25, 'end_date' => "$year-12-05", 'coupon' => 'BFCM', 'widget_title' => __( 'Ultimate Cursor — Black Friday Sale', 'ultimate-cursor' ), 'notice_title' => __( 'Black Friday Sale — Ultimate Cursor Pro', 'ultimate-cursor' ), 'description' => __( 'The biggest sale of the year! Unlock 10+ premium cursor effects, advanced customisation & priority support.', 'ultimate-cursor' ), 'button_text' => __( 'Grab 25% OFF', 'ultimate-cursor' ), 'accent' => '#f43f5e', 'accent_secondary' => '#ec4899', 'gradient' => 'linear-gradient(135deg, #0f172a 0%, #1e1b4b 40%, #581c87 75%, #7c3aed 100%)', 'icon' => 'flame', 'features' => $features, ); } // Regular promo windows: 20th of current month to 10th of next month. $day = (int) current_time( 'j' ); $month = (int) current_time( 'n' ); if ( $day >= 20 || $day <= 10 ) { if ( $day >= 20 ) { $next_month = $month === 12 ? 1 : $month + 1; $next_year = $month === 12 ? (int) $year + 1 : (int) $year; $end_date = sprintf( '%04d-%02d-10', $next_year, $next_month ); } else { $end_date = sprintf( '%s-%02d-10', $year, $month ); } return array( 'key' => 'regular', 'discount' => 20, 'end_date' => $end_date, 'coupon' => 'UNLOCKPRO', 'widget_title' => __( 'Ultimate Cursor — Limited Offer', 'ultimate-cursor' ), 'notice_title' => __( 'Limited Time Offer — Ultimate Cursor Pro', 'ultimate-cursor' ), 'description' => __( 'Upgrade to Ultimate Cursor Pro — premium effects, advanced customisation & priority support.', 'ultimate-cursor' ), 'button_text' => __( 'Get Pro — 20% OFF', 'ultimate-cursor' ), 'accent' => '#6366f1', 'accent_secondary' => '#818cf8', 'gradient' => 'linear-gradient(135deg, #0f172a 0%, #1e293b 50%, #334155 100%)', 'icon' => 'rocket', 'features' => $features, ); } return null; } /* ------------------------------------------------------------------ * 30-day dismiss helpers (server-side via user meta) * ----------------------------------------------------------------*/ /** * Inline SVG for a campaign icon key. * * Emojis render inconsistently (or as tofu boxes) on some OS/browser * combinations, so campaign icons ship as SVGs drawn in the campaign * accent color instead. * * @param string $key Icon key: 'pumpkin', 'flame', or 'rocket'. * @return string SVG markup (safe, static; echo through wp_kses with * self::get_svg_kses_allowed()). */ private function get_icon_svg( $key ) { $icons = array( 'pumpkin' => '', 'flame' => '', 'rocket' => '', ); return isset( $icons[ $key ] ) ? $icons[ $key ] : ''; } /** * Allowed tags/attributes for echoing the campaign icon SVGs. * * @return array wp_kses allowed-HTML array. */ private function get_svg_kses_allowed() { return array( 'svg' => array( 'width' => true, 'height' => true, 'viewbox' => true, 'fill' => true, 'aria-hidden' => true, 'focusable' => true, ), 'path' => array( 'd' => true, 'fill' => true, ), ); } /** * Check if a promo type was dismissed within the last 30 days. * * @param string $type 'widget' or 'notice'. * @return bool */ private function is_dismissed( $type ) { $meta_key = 'uc_dismissed_promo_' . $type; $dismissed = get_user_meta( get_current_user_id(), $meta_key, true ); if ( empty( $dismissed ) ) { return false; } $dismissed_time = (int) $dismissed; $elapsed_days = ( time() - $dismissed_time ) / DAY_IN_SECONDS; if ( $elapsed_days >= self::DISMISS_DAYS ) { // Expired — remove stale meta and allow display. delete_user_meta( get_current_user_id(), $meta_key ); return false; } return true; } /** * Record a dismissal timestamp for a promo type. * * @param string $type 'widget' or 'notice'. */ private function dismiss( $type ) { $meta_key = 'uc_dismissed_promo_' . $type; update_user_meta( get_current_user_id(), $meta_key, time() ); } /* ------------------------------------------------------------------ * Dashboard Widget * ----------------------------------------------------------------*/ /** * Register the dashboard widget. */ public function add_dashboard_widget() { if ( ! current_user_can( 'manage_options' ) ) { return; } $campaign = $this->get_campaign(); if ( ! $campaign ) { return; } if ( $this->is_dismissed( 'widget' ) ) { return; } wp_add_dashboard_widget( 'ultimate_cursor_promo_widget', $campaign['widget_title'], array( $this, 'render_dashboard_widget' ), null, null, 'column4', 'high' ); } /** * Render the dashboard widget body. */ public function render_dashboard_widget() { $c = $this->get_campaign(); if ( ! $c ) { return; } $nonce = wp_create_nonce( 'uc_dismiss_promo_widget' ); $campaign_class = 'uc-campaign-' . $c['key']; ?>
get_campaign(); if ( ! $c ) { return; } if ( $this->is_dismissed( 'notice' ) ) { return; } $notice_id = 'uc-promo-notice-' . $c['key'] . '-' . current_time( 'Y' ); $nonce = wp_create_nonce( 'uc_dismiss_promo_notice' ); $campaign_class = 'uc-campaign-' . $c['key']; ?> dismiss( 'widget' ); wp_send_json_success(); } /** * Persist notice dismissal for 30 days. */ public function ajax_dismiss_notice() { check_ajax_referer( 'uc_dismiss_promo_notice', 'nonce' ); if ( ! current_user_can( 'manage_options' ) ) { wp_send_json_error( 'Forbidden', 403 ); } $this->dismiss( 'notice' ); wp_send_json_success(); } /* ------------------------------------------------------------------ * Assets (CSS + JS) * ----------------------------------------------------------------*/ /** * Enqueue inline styles and footer scripts on relevant admin pages. */ public function enqueue_assets( $hook ) { if ( ! current_user_can( 'manage_options' ) ) { return; } $campaign = $this->get_campaign(); if ( ! $campaign ) { return; } // Attach inline CSS to an existing core handle. wp_add_inline_style( 'wp-admin', $this->get_css() ); // Print JS in footer. add_action( 'admin_footer', array( $this, 'print_scripts' ) ); } /** * All CSS in one method — widget + notice. */ private function get_css() { return ' /* === Ultimate Cursor Promo Widget === */ #ultimate_cursor_promo_widget .inside { padding: 0; margin:0; } #ultimate_cursor_promo_widget .postbox-header { display: none; } .uc-promo-widget { position: relative; color: #f1f5f9; // border-radius: 14px; padding: 28px 22px 22px; text-align: center; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, sans-serif; overflow: hidden; } /* Ambient glow effect */ .uc-pw-glow { position: absolute; top: -40%; right: -20%; width: 200px; height: 200px; background: var(--uc-accent, #6366f1); border-radius: 50%; opacity: 0.12; filter: blur(60px); pointer-events: none; animation: uc-glow-pulse 4s ease-in-out infinite; } @keyframes uc-glow-pulse { 0%, 100% { opacity: 0.10; transform: scale(1); } 50% { opacity: 0.20; transform: scale(1.15); } } /* Header */ .uc-pw-header { display: flex; align-items: center; justify-content: center; gap: 10px; margin-bottom: 16px; } .uc-pw-icon { font-size: 28px; line-height: 1; animation: uc-icon-bounce 2s ease-in-out infinite; } @keyframes uc-icon-bounce { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-4px); } } .uc-pw-badge { display: inline-flex; align-items: center; background: var(--uc-accent, #6366f1); color: #fff; font-size: 12px; font-weight: 800; padding: 5px 14px; border-radius: 20px; letter-spacing: 0.8px; text-transform: uppercase; box-shadow: 0 2px 12px rgba(0,0,0,0.25), inset 0 1px 0 rgba(255,255,255,0.15); animation: uc-badge-glow 3s ease-in-out infinite; } @keyframes uc-badge-glow { 0%, 100% { box-shadow: 0 2px 12px rgba(0,0,0,0.25), inset 0 1px 0 rgba(255,255,255,0.15); } 50% { box-shadow: 0 2px 20px var(--uc-accent, rgba(99,102,241,0.5)), inset 0 1px 0 rgba(255,255,255,0.15); } } /* Description */ .uc-pw-desc { font-size: 13px; line-height: 1.65; color: #cbd5e1; margin: 0 0 16px; } /* Feature list */ .uc-pw-features { list-style: none; margin: 0 0 18px; padding: 0; display: flex; flex-direction: column; gap: 8px; } .uc-pw-features li { display: flex; align-items: center; gap: 8px; font-size: 12px; color: #e2e8f0; justify-content: center; } .uc-pw-features li svg { flex-shrink: 0; } /* Countdown */ .uc-pw-countdown { display: inline-flex; align-items: center; gap: 6px; font-size: 12px; color: #94a3b8; margin-bottom: 16px; background: rgba(255,255,255,0.05); padding: 6px 14px; border-radius: 8px; border: 1px solid rgba(255,255,255,0.08); } .uc-pw-cd-value { color: #f8fafc; font-weight: 700; font-variant-numeric: tabular-nums; font-size: 13px; } /* Coupon */ .uc-pw-coupon { display: flex; align-items: center; justify-content: center; gap: 8px; margin-bottom: 18px; font-size: 12px; color: #94a3b8; } .uc-pw-coupon-code { position: relative; display: inline-flex; align-items: center; gap: 6px; background: rgba(255,255,255,0.08); border: 1px dashed rgba(255,255,255,0.25); color: #f8fafc; font-family: "SF Mono", "Fira Code", "Courier New", monospace; font-size: 13px; font-weight: 700; letter-spacing: 2px; padding: 6px 14px; border-radius: 8px; cursor: pointer; transition: all 0.25s ease; } .uc-pw-coupon-code:hover { background: rgba(255,255,255,0.15); border-color: rgba(255,255,255,0.4); transform: translateY(-1px); } .uc-pw-copy-icon { opacity: 0.6; transition: opacity 0.2s; } .uc-pw-coupon-code:hover .uc-pw-copy-icon { opacity: 1; } .uc-pw-code-copied { display: none; position: absolute; inset: 0; background: #22c55e; color: #fff; border-radius: 7px; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; font-size: 11px; font-weight: 600; letter-spacing: 0; align-items: center; justify-content: center; } .uc-pw-coupon-code.is-copied .uc-pw-code-copied { display: flex; } .uc-pw-coupon-code.is-copied .uc-pw-code-text, .uc-pw-coupon-code.is-copied .uc-pw-copy-icon { visibility: hidden; } /* CTA Button */ .uc-pw-cta { display: inline-flex; align-items: center; justify-content: center; gap: 6px; background: var(--uc-accent, #6366f1); color: #fff !important; text-decoration: none !important; font-weight: 700; font-size: 13px; padding: 11px 28px; border-radius: 10px; transition: all 0.25s ease; box-shadow: 0 4px 14px rgba(0,0,0,0.3); width: 100%; box-sizing: border-box; } .uc-pw-cta:hover { transform: translateY(-2px); box-shadow: 0 6px 20px rgba(0,0,0,0.4); color: #fff !important; filter: brightness(1.1); } .uc-pw-cta:active { transform: translateY(0); } /* Dismiss button */ .uc-pw-dismiss { position: absolute; top: 10px; right: 10px; background: rgba(255,255,255,0.08); border: none; color: #64748b; font-size: 14px; cursor: pointer; line-height: 1; padding: 5px; border-radius: 6px; transition: all 0.2s; display: flex; align-items: center; justify-content: center; z-index: 2; } .uc-pw-dismiss:hover { color: #f1f5f9; background: rgba(255,255,255,0.15); } /* === Campaign-specific widget styles === */ /* Halloween */ .uc-campaign-halloween .uc-pw-glow { background: #ff6600; } .uc-campaign-halloween .uc-pw-badge { background: linear-gradient(135deg, #ff6600, #ff8c00); } .uc-campaign-halloween .uc-pw-cta { background: linear-gradient(135deg, #ff6600, #ff8c00); } /* Black Friday */ .uc-campaign-black_friday .uc-pw-glow { background: #f43f5e; } .uc-campaign-black_friday .uc-pw-badge { background: linear-gradient(135deg, #f43f5e, #ec4899); } .uc-campaign-black_friday .uc-pw-cta { background: linear-gradient(135deg, #f43f5e, #ec4899); } /* Regular */ .uc-campaign-regular .uc-pw-glow { background: #6366f1; } .uc-campaign-regular .uc-pw-badge { background: linear-gradient(135deg, #6366f1, #818cf8); } .uc-campaign-regular .uc-pw-cta { background: linear-gradient(135deg, #6366f1, #818cf8); } /* === Ultimate Cursor Promo Notice === */ .uc-promo-notice { border: none !important; border-radius: 8px !important; padding: 0 !important; overflow: hidden; margin: 15px 0 !important; position: relative; box-shadow: 0 4px 20px rgba(0,0,0,0.15); } .uc-pn-glow { position: absolute; top: -50%; right: -10%; width: 160px; height: 160px; background: var(--uc-accent, #6366f1); border-radius: 50%; opacity: 0.1; filter: blur(50px); pointer-events: none; animation: uc-glow-pulse 4s ease-in-out infinite; } .uc-pn-inner { display: flex; align-items: center; gap: 16px; padding: 14px 20px; color: #f1f5f9; flex-wrap: wrap; position: relative; } .uc-pn-badge-wrap { display: flex; align-items: center; gap: 8px; flex-shrink: 0; } .uc-pn-icon { font-size: 22px; line-height: 1; animation: uc-icon-bounce 2s ease-in-out infinite; } .uc-pn-discount { display: inline-flex; align-items: center; background: var(--uc-accent, #6366f1); color: #fff; font-size: 11px; font-weight: 800; padding: 4px 10px; border-radius: 14px; letter-spacing: 0.6px; text-transform: uppercase; box-shadow: 0 2px 8px rgba(0,0,0,0.2); } .uc-pn-content { display: flex; flex-direction: column; gap: 2px; flex: 1; min-width: 200px; } .uc-pn-title { font-size: 13px; font-weight: 700; color: #fff; line-height: 1.3; } .uc-pn-desc { font-size: 12px; color: #cbd5e1; line-height: 1.4; } .uc-pn-actions { display: flex; align-items: center; gap: 14px; flex-shrink: 0; margin-right:30px; } .uc-pn-timer { display: inline-flex; align-items: center; gap: 5px; font-size: 12px; color: #94a3b8; white-space: nowrap; background: rgba(255,255,255,0.06); padding: 5px 10px; border-radius: 6px; } .uc-pn-timer svg { opacity: 0.7; } .uc-pn-timer strong { color: #fff; font-variant-numeric: tabular-nums; } .uc-pn-btn { display: inline-flex; align-items: center; gap: 5px; background: var(--uc-accent, #6366f1) !important; color: #fff !important; text-decoration: none !important; font-size: 12px; font-weight: 700; padding: 8px 18px; border-radius: 8px; white-space: nowrap; transition: all 0.25s ease; box-shadow: 0 2px 10px rgba(0,0,0,0.2); } .uc-pn-btn:hover { transform: translateY(-1px); box-shadow: 0 4px 16px rgba(0,0,0,0.3); color: #fff !important; filter: brightness(1.1); } .uc-pn-dismiss { position: absolute; top: 10px; right: 0px; transform: translateY(-50%); background: rgba(255,255,255,0.08); border: none; color: #64748b; cursor: pointer; padding: 5px; border-radius: 6px; transition: all 0.2s; display: flex; align-items: center; justify-content: center; z-index: 2; } .uc-pn-dismiss:hover { color: #f1f5f9; background: rgba(255,255,255,0.15); } /* Campaign-specific notice styles */ .uc-promo-notice.uc-campaign-halloween .uc-pn-discount { background: linear-gradient(135deg, #ff6600, #ff8c00); } .uc-promo-notice.uc-campaign-halloween .uc-pn-btn { background: linear-gradient(135deg, #ff6600, #ff8c00) !important; } .uc-promo-notice.uc-campaign-black_friday .uc-pn-discount { background: linear-gradient(135deg, #f43f5e, #ec4899); } .uc-promo-notice.uc-campaign-black_friday .uc-pn-btn { background: linear-gradient(135deg, #f43f5e, #ec4899) !important; } .uc-promo-notice.uc-campaign-regular .uc-pn-discount { background: linear-gradient(135deg, #6366f1, #818cf8); } .uc-promo-notice.uc-campaign-regular .uc-pn-btn { background: linear-gradient(135deg, #6366f1, #818cf8) !important; } @media (max-width: 782px) { .uc-pn-inner { flex-direction: column; align-items: flex-start; gap: 10px; padding: 14px 44px 14px 16px; } .uc-pn-actions { flex-wrap: wrap; gap: 8px; } .uc-pn-btn { margin-left: 0; } } '; } /** * Minimal JS — handles countdowns, clipboard copy, and dismiss persistence. */ public function print_scripts() { ?>