افزونه تخفیف روز وردپرس؛ نمایش کد تخفیف با قابلیت کپی و Popup

افزونه تخفیف روز وردپرس؛ نمایش کد تخفیف با قابلیت کپی و Popup

افزونه تخفیف روز وردپرس؛ نمایش حرفه‌ای کد تخفیف با قابلیت کپی افزونه تخفیف روز یک ابزار وردپرسی برای نمایش متن تخفیف و کد تخفیف در بخش‌های مختلف سایت است. این افزونه امکان مدیریت محتوای تخفیف، شخصی‌سازی ظاهر کد و استفاده از شورت‌کد را فراهم می‌کند و در سمت کاربر نیز

کد
/**
 * Plugin Name: تخفیف روز
 * Description: نمایش یک متن و یک کد تخفیف با قابلیت کپی، Popup و تنظیم کامل ظاهر.
 * Version: 1.5.0
 * Author: SAJAD.TAEB

 * Requires at least: 5.8
 * Requires PHP: 7.4
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

final class Gildata_Daily_Discount {

	const VERSION = '1.5.0';

	const TEXT_OPTION          = 'gdd_text';
	const CODE_OPTION          = 'gdd_code';
	const TEXT_COLOR_OPTION    = 'gdd_text_color';
	const CODE_COLOR_OPTION    = 'gdd_code_color';
	const CODE_BG_OPTION       = 'gdd_code_bg';
	const TEXT_SIZE_OPTION     = 'gdd_text_size';
	const CODE_SIZE_OPTION     = 'gdd_code_size';
	const BORDER_WIDTH_OPTION  = 'gdd_border_width';
	const BORDER_STYLE_OPTION  = 'gdd_border_style';
	const BORDER_RADIUS_OPTION = 'gdd_border_radius';

	/**
	 * Constructor
	 */
	public function __construct() {

		add_action(
			'admin_menu',
			array( $this, 'admin_menu' )
		);

		add_action(
			'admin_enqueue_scripts',
			array( $this, 'admin_assets' )
		);

		add_action(
			'wp_enqueue_scripts',
			array( $this, 'frontend_assets' )
		);

		add_shortcode(
			'daily_discount',
			array( $this, 'shortcode' )
		);
	}

	/**
	 * =========================================================
	 * ADMIN MENU
	 * =========================================================
	 */
	public function admin_menu() {

		add_menu_page(
			'تخفیف روز',
			'تخفیف روز',
			'manage_options',
			'gdd-daily-discount',
			array( $this, 'admin_page' ),
			'dashicons-tickets-alt',
			25
		);
	}

	/**
	 * =========================================================
	 * ADMIN PAGE
	 * =========================================================
	 */
	public function admin_page() {

		if ( ! current_user_can( 'manage_options' ) ) {
			return;
		}

		$saved = false;

		/**
		 * =====================================================
		 * SAVE
		 * =====================================================
		 */
		if ( isset( $_POST['gdd_save'] ) ) {

			if (
				! isset( $_POST['gdd_nonce'] ) ||
				! wp_verify_nonce(
					sanitize_text_field(
						wp_unslash(
							$_POST['gdd_nonce']
						)
					),
					'gdd_save_action'
				)
			) {
				return;
			}

			/**
			 * متن
			 */
			$text = isset( $_POST['gdd_text'] )
				? sanitize_textarea_field(
					wp_unslash(
						$_POST['gdd_text']
					)
				)
				: '';

			/**
			 * کد
			 */
			$code = isset( $_POST['gdd_code'] )
				? sanitize_text_field(
					wp_unslash(
						$_POST['gdd_code']
					)
				)
				: '';

			/**
			 * رنگ متن
			 */
			$text_color = isset( $_POST['gdd_text_color'] )
				? sanitize_hex_color(
					wp_unslash(
						$_POST['gdd_text_color']
					)
				)
				: false;

			/**
			 * رنگ متن کد
			 */
			$code_color = isset( $_POST['gdd_code_color'] )
				? sanitize_hex_color(
					wp_unslash(
						$_POST['gdd_code_color']
					)
				)
				: false;

			/**
			 * بکگراند کد
			 */
			$code_bg = isset( $_POST['gdd_code_bg'] )
				? sanitize_hex_color(
					wp_unslash(
						$_POST['gdd_code_bg']
					)
				)
				: false;

			/**
			 * سایز متن
			 */
			$text_size = isset( $_POST['gdd_text_size'] )
				? absint(
					$_POST['gdd_text_size']
				)
				: 14;

			/**
			 * سایز کد
			 */
			$code_size = isset( $_POST['gdd_code_size'] )
				? absint(
					$_POST['gdd_code_size']
				)
				: 14;

			/**
			 * ضخامت حاشیه
			 */
			$border_width = isset( $_POST['gdd_border_width'] )
				? absint(
					$_POST['gdd_border_width']
				)
				: 1;

			/**
			 * گردی
			 */
			$border_radius = isset( $_POST['gdd_border_radius'] )
				? absint(
					$_POST['gdd_border_radius']
				)
				: 6;

			/**
			 * نوع حاشیه
			 */
			$border_style = isset( $_POST['gdd_border_style'] )
				? sanitize_key(
					wp_unslash(
						$_POST['gdd_border_style']
					)
				)
				: 'solid';

			/**
			 * استایل‌های مجاز
			 */
			$allowed_styles = array(
				'solid',
				'dashed',
				'dotted',
			);

			if (
				! in_array(
					$border_style,
					$allowed_styles,
					true
				)
			) {
				$border_style = 'solid';
			}

			/**
			 * محدودیت سایز متن
			 */
			$text_size = min(
				max(
					$text_size,
					8
				),
				60
			);

			/**
			 * محدودیت سایز کد
			 */
			$code_size = min(
				max(
					$code_size,
					8
				),
				60
			);

			/**
			 * محدودیت حاشیه
			 */
			$border_width = min(
				max(
					$border_width,
					0
				),
				10
			);

			/**
			 * محدودیت گردی
			 */
			$border_radius = min(
				max(
					$border_radius,
					0
				),
				50
			);

			/**
			 * مقادیر پیش‌فرض
			 */
			if ( ! $text_color ) {
				$text_color = '#FFFFFF';
			}

			if ( ! $code_color ) {
				$code_color = '#FFFFFF';
			}

			if ( ! $code_bg ) {
				$code_bg = '#0F6B4F';
			}

			/**
			 * =================================================
			 * SAVE OPTIONS
			 * =================================================
			 *
			 * فقط یک متن و یک کد ذخیره می‌شود.
			 * مقدار جدید جایگزین قبلی خواهد شد.
			 */

			update_option(
				self::TEXT_OPTION,
				$text,
				false
			);

			update_option(
				self::CODE_OPTION,
				$code,
				false
			);

			update_option(
				self::TEXT_COLOR_OPTION,
				$text_color,
				false
			);

			update_option(
				self::CODE_COLOR_OPTION,
				$code_color,
				false
			);

			update_option(
				self::CODE_BG_OPTION,
				$code_bg,
				false
			);

			update_option(
				self::TEXT_SIZE_OPTION,
				$text_size,
				false
			);

			update_option(
				self::CODE_SIZE_OPTION,
				$code_size,
				false
			);

			update_option(
				self::BORDER_WIDTH_OPTION,
				$border_width,
				false
			);

			update_option(
				self::BORDER_STYLE_OPTION,
				$border_style,
				false
			);

			update_option(
				self::BORDER_RADIUS_OPTION,
				$border_radius,
				false
			);

			$saved = true;
		}

		/**
		 * =====================================================
		 * GET OPTIONS
		 * =====================================================
		 */

		$text = get_option(
			self::TEXT_OPTION,
			''
		);

		$code = get_option(
			self::CODE_OPTION,
			''
		);

		$text_color = get_option(
			self::TEXT_COLOR_OPTION,
			'#FFFFFF'
		);

		$code_color = get_option(
			self::CODE_COLOR_OPTION,
			'#FFFFFF'
		);

		$code_bg = get_option(
			self::CODE_BG_OPTION,
			'#0F6B4F'
		);

		$text_size = absint(
			get_option(
				self::TEXT_SIZE_OPTION,
				14
			)
		);

		$code_size = absint(
			get_option(
				self::CODE_SIZE_OPTION,
				14
			)
		);

		$border_width = absint(
			get_option(
				self::BORDER_WIDTH_OPTION,
				1
			)
		);

		$border_style = get_option(
			self::BORDER_STYLE_OPTION,
			'solid'
		);

		$border_radius = absint(
			get_option(
				self::BORDER_RADIUS_OPTION,
				6
			)
		);

		/**
		 * اعتبارسنجی رنگ‌ها
		 */
		if (
			! sanitize_hex_color(
				$text_color
			)
		) {
			$text_color = '#FFFFFF';
		}

		if (
			! sanitize_hex_color(
				$code_color
			)
		) {
			$code_color = '#FFFFFF';
		}

		if (
			! sanitize_hex_color(
				$code_bg
			)
		) {
			$code_bg = '#0F6B4F';
		}

		?>

		<div class="gdd-admin-wrap">

			<!-- =================================================
			     HEADER
			================================================= -->

			<div class="gdd-admin-head">

				<div class="gdd-admin-head-content">

					<div class="gdd-admin-logo">

						<span class="dashicons dashicons-tickets-alt"></span>

					</div>

					<div>

						<h1>
							تخفیف روز
						</h1>

						<p>
							مدیریت متن و کد تخفیف سایت
						</p>

					</div>

				</div>

				<div class="gdd-admin-status">

					<span></span>

					فعال

				</div>

			</div>

			<!-- =================================================
			     SUCCESS
			================================================= -->

			<?php if ( $saved ) : ?>

				<div class="gdd-admin-success">

					<span class="dashicons dashicons-yes-alt"></span>

					تغییرات با موفقیت ذخیره شد.

				</div>

			<?php endif; ?>

			<!-- =================================================
			     GRID
			================================================= -->

			<div class="gdd-admin-grid">

				<!-- =================================================
				     MAIN FORM
				================================================= -->

				<div class="gdd-admin-card gdd-main-card">

					<div class="gdd-card-heading">

						<div class="gdd-card-icon">

							<span class="dashicons dashicons-edit"></span>

						</div>

						<div>

							<h2>
								اطلاعات تخفیف
							</h2>

							<p>
								متن و کد تخفیف فعال
							</p>

						</div>

					</div>

					<form method="post">

						<?php

						wp_nonce_field(
							'gdd_save_action',
							'gdd_nonce'
						);

						?>

						<!-- متن -->

						<div class="gdd-field">

							<label for="gdd_text">
								متن تخفیف
							</label>

							<textarea
								id="gdd_text"
								name="gdd_text"
								rows="4"
								placeholder="تخفیف امروز 20% برای خرید بالای 2 میلیون تومان"
							><?php echo esc_textarea( $text ); ?></textarea>

							<div class="gdd-field-help">
								فقط یک متن فعال در سایت نمایش داده می‌شود.
							</div>

						</div>

						<!-- کد -->

						<div class="gdd-field">

							<label for="gdd_code">
								کد تخفیف
							</label>

							<input
								type="text"
								id="gdd_code"
								name="gdd_code"
								value="<?php echo esc_attr( $code ); ?>"
								placeholder="T20"
								autocomplete="off"
								maxlength="100"
							/>

							<div class="gdd-field-help">
								با کلیک روی این کد، مقدار آن کپی می‌شود.
							</div>

						</div>

						<!-- =================================================
						     APPEARANCE
						================================================= -->

						<div class="gdd-section-title">

							<span>
								تنظیمات ظاهر
							</span>

						</div>

						<div class="gdd-settings-grid">

							<!-- رنگ متن -->

							<div class="gdd-setting">

								<label>
									رنگ متن
								</label>

								<div class="gdd-color-control">

									<input
										type="color"
										id="gdd_text_color"
										name="gdd_text_color"
										value="<?php echo esc_attr( $text_color ); ?>"
									/>

									<input
										type="text"
										class="gdd-color-value"
										value="<?php echo esc_attr( $text_color ); ?>"
										readonly
									/>

								</div>

							</div>

							<!-- رنگ کد -->

							<div class="gdd-setting">

								<label>
									رنگ متن کد
								</label>

								<div class="gdd-color-control">

									<input
										type="color"
										id="gdd_code_color"
										name="gdd_code_color"
										value="<?php echo esc_attr( $code_color ); ?>"
									/>

									<input
										type="text"
										class="gdd-color-value"
										value="<?php echo esc_attr( $code_color ); ?>"
										readonly
									/>

								</div>

							</div>

							<!-- بکگراند کد -->

							<div class="gdd-setting">

								<label>
									پس‌زمینه کد تخفیف
								</label>

								<div class="gdd-color-control">

									<input
										type="color"
										id="gdd_code_bg"
										name="gdd_code_bg"
										value="<?php echo esc_attr( $code_bg ); ?>"
									/>

									<input
										type="text"
										class="gdd-color-value"
										value="<?php echo esc_attr( $code_bg ); ?>"
										readonly
									/>

								</div>

							</div>

							<!-- سایز متن -->

							<div class="gdd-setting">

								<label for="gdd_text_size">
									سایز متن
								</label>

								<div class="gdd-range-row">

									<input
										type="range"
										id="gdd_text_size"
										name="gdd_text_size"
										min="8"
										max="60"
										value="<?php echo esc_attr( $text_size ); ?>"
									/>

									<strong id="gdd_text_size_value">

										<?php
										echo esc_html(
											$text_size
										);
										?>px

									</strong>

								</div>

							</div>

							<!-- سایز کد -->

							<div class="gdd-setting">

								<label for="gdd_code_size">
									سایز کد تخفیف
								</label>

								<div class="gdd-range-row">

									<input
										type="range"
										id="gdd_code_size"
										name="gdd_code_size"
										min="8"
										max="60"
										value="<?php echo esc_attr( $code_size ); ?>"
									/>

									<strong id="gdd_code_size_value">

										<?php
										echo esc_html(
											$code_size
										);
										?>px

									</strong>

								</div>

							</div>

							<!-- ضخامت -->

							<div class="gdd-setting">

								<label for="gdd_border_width">
									ضخامت حاشیه کد
								</label>

								<div class="gdd-range-row">

									<input
										type="range"
										id="gdd_border_width"
										name="gdd_border_width"
										min="0"
										max="10"
										value="<?php echo esc_attr( $border_width ); ?>"
									/>

									<strong id="gdd_border_width_value">

										<?php
										echo esc_html(
											$border_width
										);
										?>px

									</strong>

								</div>

							</div>

							<!-- گردی -->

							<div class="gdd-setting">

								<label for="gdd_border_radius">
									گردی گوشه کد
								</label>

								<div class="gdd-range-row">

									<input
										type="range"
										id="gdd_border_radius"
										name="gdd_border_radius"
										min="0"
										max="50"
										value="<?php echo esc_attr( $border_radius ); ?>"
									/>

									<strong id="gdd_border_radius_value">

										<?php
										echo esc_html(
											$border_radius
										);
										?>px

									</strong>

								</div>

							</div>

							<!-- نوع حاشیه -->

							<div class="gdd-setting">

								<label for="gdd_border_style">
									نوع حاشیه
								</label>

								<select
									id="gdd_border_style"
									name="gdd_border_style"
								>

									<option
										value="solid"
										<?php selected(
											$border_style,
											'solid'
										); ?>
									>
										ساده
									</option>

									<option
										value="dashed"
										<?php selected(
											$border_style,
											'dashed'
										); ?>
									>
										خط‌چین
									</option>

									<option
										value="dotted"
										<?php selected(
											$border_style,
											'dotted'
										); ?>
									>
										نقطه‌ای
									</option>

								</select>

							</div>

						</div>

						<!-- =================================================
						     SAVE
						================================================= -->

						<div class="gdd-form-footer">

							<button
								type="submit"
								name="gdd_save"
								class="gdd-save-button"
							>

								<span class="dashicons dashicons-saved"></span>

								ذخیره تغییرات

							</button>

						</div>

					</form>

				</div>

				<!-- =================================================
				     PREVIEW
				================================================= -->

				<div class="gdd-admin-card">

					<div class="gdd-card-heading">

						<div class="gdd-card-icon">

							<span class="dashicons dashicons-visibility"></span>

						</div>

						<div>

							<h2>
								پیش‌نمایش
							</h2>

							<p>
								نمایش زنده
							</p>

						</div>

					</div>

					<div class="gdd-preview-area">

						<div
							id="gdd-live-preview"
							class="gdd-preview-content"

							style="
								--gdd-text-color: <?php echo esc_attr( $text_color ); ?>;
								--gdd-code-color: <?php echo esc_attr( $code_color ); ?>;
								--gdd-code-bg: <?php echo esc_attr( $code_bg ); ?>;
								--gdd-text-size: <?php echo esc_attr( $text_size ); ?>px;
								--gdd-code-size: <?php echo esc_attr( $code_size ); ?>px;
								--gdd-border-width: <?php echo esc_attr( $border_width ); ?>px;
								--gdd-border-style: <?php echo esc_attr( $border_style ); ?>;
								--gdd-border-radius: <?php echo esc_attr( $border_radius ); ?>px;
							"
						>

							<span
								id="gdd-preview-text"
								class="gdd-preview-text"
							>

								<?php

								echo esc_html(
									$text
										? $text
										: 'تخفیف امروز 20% برای خرید بالای 2 میلیون تومان'
								);

								?>

							</span>

							<span
								class="gdd-preview-separator"
							>
								|
							</span>

							<span
								class="gdd-preview-label"
							>
								کد تخفیف :
							</span>

							<span
								id="gdd-preview-code"
								class="gdd-preview-code"
							>

								<?php

								echo esc_html(
									$code
										? $code
										: 'T20'
								);

								?>

							</span>

						</div>

					</div>

					<div class="gdd-preview-note">

						بدون بکگراند برای کل بخش و با فونت پیش‌فرض سایت.

					</div>

				</div>

				<!-- =================================================
				     SHORTCODE
				================================================= -->

				<div class="gdd-admin-card">

					<div class="gdd-card-heading">

						<div class="gdd-card-icon">

							<span class="dashicons dashicons-editor-code"></span>

						</div>

						<div>

							<h2>
								شورت‌کد
							</h2>

							<p>
								در Elementor یا هر بخش سایت استفاده کنید
							</p>

						</div>

					</div>

					<div class="gdd-shortcode-box">

						<code>
							[daily_discount]
						</code>

						<button
							type="button"
							class="gdd-copy-shortcode"
							data-gdd-copy="[daily_discount]"
						>
							کپی
						</button>

					</div>

				</div>

			</div>

		</div>

		<?php
	}

	/**
	 * =========================================================
	 * FRONTEND CSS + JS
	 * =========================================================
	 */
	public function frontend_assets() {

		wp_register_style(
			'gdd-frontend',
			false,
			array(),
			self::VERSION
		);

		wp_enqueue_style(
			'gdd-frontend'
		);

		$css = <<<'CSS'

/* =========================================================
   GDD FRONTEND
   ALL CLASSES ARE ISOLATED
========================================================= */

.gdd-discount-root {

	--gdd-text-color: #ffffff;
	--gdd-code-color: #ffffff;
	--gdd-code-bg: #0f6b4f;

	--gdd-text-size: 14px;
	--gdd-code-size: 14px;

	--gdd-border-width: 1px;
	--gdd-border-style: solid;
	--gdd-border-radius: 6px;

	display: inline-flex;

	position: relative;

	width: auto;
	max-width: 100%;

	margin: 0;
	padding: 0;

	background: transparent !important;

	border: 0 !important;

	box-shadow: none !important;

	font-family: inherit;

	direction: rtl;

	overflow: visible !important;

	box-sizing: border-box;
}


.gdd-discount-root *,
.gdd-discount-root *::before,
.gdd-discount-root *::after {

	box-sizing: border-box;

}


/* =========================================================
   CONTENT
========================================================= */

.gdd-discount-content {

	display: inline-flex;

	align-items: center;

	justify-content: center;

	flex-wrap: wrap;

	gap: 7px;

	position: relative;

	width: auto;
	max-width: 100%;

	margin: 0;
	padding: 0;

	background: transparent !important;

	border: 0 !important;

	box-shadow: none !important;

	font-family: inherit;

	overflow: visible !important;
}


/* =========================================================
   TEXT
========================================================= */

.gdd-discount-text {

	display: inline;

	margin: 0;
	padding: 0;

	background: transparent !important;

	border: 0 !important;

	box-shadow: none !important;

	font-family: inherit;

	font-size: var(--gdd-text-size);

	font-weight: inherit;

	line-height: 1.35;

	color: var(--gdd-text-color);

	white-space: normal;
}


/* =========================================================
   SEPARATOR
========================================================= */

.gdd-discount-separator {

	display: inline-flex;

	align-items: center;

	justify-content: center;

	flex: 0 0 auto;

	margin: 0 1px;

	padding: 0;

	background: transparent !important;

	border: 0 !important;

	box-shadow: none !important;

	color: var(--gdd-text-color);

	font-family: inherit;

	font-size: var(--gdd-text-size);

	font-weight: 400;

	line-height: 1;

	opacity: .75;

	user-select: none;
}


/* =========================================================
   CODE LABEL
========================================================= */

.gdd-discount-label {

	display: inline-flex;

	align-items: center;

	justify-content: center;

	flex: 0 0 auto;

	margin: 0;

	padding: 0;

	background: transparent !important;

	border: 0 !important;

	box-shadow: none !important;

	color: var(--gdd-text-color);

	font-family: inherit;

	font-size: var(--gdd-text-size);

	font-weight: inherit;

	line-height: 1.35;

	white-space: nowrap;
}


/* =========================================================
   DISCOUNT CODE
========================================================= */

.gdd-discount-code {

	display: inline-flex !important;

	align-items: center !important;

	justify-content: center !important;

	flex: 0 0 auto;

	position: relative;

	box-sizing: border-box !important;

	width: auto !important;

	min-width: 0 !important;

	min-height: 0 !important;

	height: auto !important;

	margin: 0 !important;

	/*
	 * ارتفاع کم و جمع‌وجور
	 */
	padding: 3px 10px !important;

	background:
		var(--gdd-code-bg) !important;

	border:
		var(--gdd-border-width)
		var(--gdd-border-style)
		var(--gdd-code-color) !important;

	border-radius:
		var(--gdd-border-radius) !important;

	box-shadow:
		none !important;

	font-family:
		inherit !important;

	font-size:
		var(--gdd-code-size) !important;

	font-weight:
		700 !important;

	line-height:
		1.2 !important;

	color:
		var(--gdd-code-color) !important;

	text-decoration:
		none !important;

	text-align:
		center !important;

	white-space:
		nowrap !important;

	cursor:
		pointer;

	appearance:
		none !important;

	-webkit-appearance:
		none !important;

	outline:
		none;

	vertical-align:
		middle;

	transition:
		transform .18s ease,
		box-shadow .18s ease,
		filter .18s ease,
		opacity .18s ease;
}


/*
 * حذف ظاهر احتمالی قالب
 */
.gdd-discount-code:hover,
.gdd-discount-code:focus,
.gdd-discount-code:active {

	background:
		var(--gdd-code-bg) !important;

	color:
		var(--gdd-code-color) !important;
}


/* =========================================================
   HOVER
========================================================= */

.gdd-discount-code:hover {

	transform:
		translateY(-1px);

	box-shadow:
		0 4px 12px
		rgba(0,0,0,.12) !important;

	filter:
		brightness(1.05);
}


/* =========================================================
   ACTIVE
========================================================= */

.gdd-discount-code:active {

	transform:
		translateY(0)
		scale(.97);

	box-shadow:
		none !important;
}


/* =========================================================
   FOCUS
========================================================= */

.gdd-discount-code:focus-visible {

	outline:
		2px solid
		var(--gdd-code-color);

	outline-offset:
		2px;
}


/* =========================================================
   POPUP
========================================================= */

.gdd-discount-popup {

	position: fixed;

	z-index: 2147483647;

	display: block;

	width: max-content;

	max-width:
		calc(100vw - 24px);

	padding:
		8px 12px;

	background:
		linear-gradient(
			135deg,
			#111827 0%,
			#1f2937 100%
		) !important;

	border:
		1px solid
		rgba(255,255,255,.09) !important;

	border-radius:
		9px;

	box-shadow:
		0 10px 30px
		rgba(0,0,0,.20),
		0 3px 8px
		rgba(0,0,0,.10);

	color:
		#ffffff !important;

	font-family:
		inherit;

	font-size:
		12px;

	font-weight:
		500;

	line-height:
		1.45;

	text-align:
		center;

	white-space:
		nowrap;

	opacity:
		0;

	visibility:
		hidden;

	pointer-events:
		none;

	transform:
		translateY(6px)
		scale(.96);

	transition:
		opacity .18s ease,
		transform .18s cubic-bezier(.2,.8,.2,1),
		visibility .18s ease;
}


/* =========================================================
   POPUP ARROW
========================================================= */

.gdd-discount-popup::after {

	content: "";

	position: absolute;

	left: 50%;

	bottom: -5px;

	width: 10px;

	height: 10px;

	background:
		#1f2937;

	border-right:
		1px solid
		rgba(255,255,255,.06);

	border-bottom:
		1px solid
		rgba(255,255,255,.06);

	transform:
		translateX(-50%)
		rotate(45deg);
}


/* =========================================================
   POPUP VISIBLE
========================================================= */

.gdd-discount-popup.gdd-popup-visible {

	opacity:
		1;

	visibility:
		visible;

	transform:
		translateY(0)
		scale(1);
}


/* =========================================================
   POPUP BOTTOM
========================================================= */

.gdd-discount-popup.gdd-popup-bottom {

	transform:
		translateY(-6px)
		scale(.96);
}

.gdd-discount-popup.gdd-popup-bottom.gdd-popup-visible {

	transform:
		translateY(0)
		scale(1);
}

.gdd-discount-popup.gdd-popup-bottom::after {

	top:
		-5px;

	bottom:
		auto;

	transform:
		translateX(-50%)
		rotate(225deg);
}


/* =========================================================
   COPY MESSAGE
========================================================= */

.gdd-copy-message {

	position: fixed;

	left: 50%;

	bottom: 24px;

	z-index: 2147483647;

	display: flex;

	align-items: center;

	gap: 7px;

	padding:
		8px 14px;

	background:
		linear-gradient(
			135deg,
			#111827,
			#374151
		) !important;

	border:
		1px solid
		rgba(255,255,255,.08) !important;

	border-radius:
		8px;

	box-shadow:
		0 10px 30px
		rgba(0,0,0,.18);

	color:
		#fff !important;

	font-family:
		inherit;

	font-size:
		13px;

	line-height:
		1.5;

	white-space:
		nowrap;

	transform:
		translateX(-50%)
		translateY(10px)
		scale(.96);

	opacity:
		0;

	visibility:
		hidden;

	pointer-events:
		none;

	transition:
		opacity .2s ease,
		transform .2s ease,
		visibility .2s ease;
}


/* =========================================================
   COPY MESSAGE VISIBLE
========================================================= */

.gdd-copy-message.gdd-copy-visible {

	opacity:
		1;

	visibility:
		visible;

	transform:
		translateX(-50%)
		translateY(0)
		scale(1);
}


/* =========================================================
   MOBILE
========================================================= */

@media (max-width: 600px) {

	.gdd-discount-content {

		gap:
			5px;

	}

	.gdd-discount-text,
	.gdd-discount-separator,
	.gdd-discount-label {

		line-height:
			1.35;

	}

	.gdd-discount-code {

		padding:
			3px 9px !important;

	}

	.gdd-discount-popup {

		padding:
			7px 10px;

		font-size:
			11px;

	}

}

CSS;

		wp_add_inline_style(
			'gdd-frontend',
			$css
		);

		/**
		 * =====================================================
		 * JAVASCRIPT
		 * =====================================================
		 */

		wp_register_script(
			'gdd-frontend',
			false,
			array(),
			self::VERSION,
			true
		);

		wp_enqueue_script(
			'gdd-frontend'
		);

		$js = <<<'JS'

(function () {

	'use strict';

	var gddPopup = null;

	var gddCopyTimer = null;


	/* =========================================================
	   CREATE POPUP
	========================================================= */

	function gddCreatePopup() {

		if ( gddPopup ) {
			return gddPopup;
		}

		gddPopup =
			document.createElement(
				'div'
			);

		gddPopup.className =
			'gdd-discount-popup';

		gddPopup.textContent =
			'برای کپی کردن کلیک کنید';

		/*
		 * Popup مستقیماً داخل body
		 * قرار می‌گیرد تا توسط Elementor
		 * یا overflow:hidden بریده نشود.
		 */
		document.body.appendChild(
			gddPopup
		);

		return gddPopup;
	}


	/* =========================================================
	   POSITION POPUP
	========================================================= */

	function gddPositionPopup( button ) {

		var popup =
			gddCreatePopup();

		var rect =
			button.getBoundingClientRect();

		popup.style.left =
			'0px';

		popup.style.top =
			'0px';

		var popupWidth =
			popup.offsetWidth;

		var popupHeight =
			popup.offsetHeight;

		var margin =
			10;

		var left =
			rect.left +
			(
				rect.width /
				2
			) -
			(
				popupWidth /
				2
			);

		var top =
			rect.top -
			popupHeight -
			12;

		popup.classList.remove(
			'gdd-popup-bottom'
		);


		/*
		 * جلوگیری از خروج از سمت چپ
		 */
		if (
			left <
			margin
		) {

			left =
				margin;

		}


		/*
		 * جلوگیری از خروج از سمت راست
		 */
		if (
			left +
			popupWidth >
			window.innerWidth -
			margin
		) {

			left =
				window.innerWidth -
				popupWidth -
				margin;

		}


		/*
		 * اگر بالای صفحه جا نبود
		 */
		if (
			top <
			margin
		) {

			top =
				rect.bottom +
				12;

			popup.classList.add(
				'gdd-popup-bottom'
			);

		}


		/*
		 * جلوگیری از خروج پایین صفحه
		 */
		if (
			top +
			popupHeight >
			window.innerHeight -
			margin
		) {

			top =
				window.innerHeight -
				popupHeight -
				margin;

		}


		popup.style.left =
			Math.round(
				left
			) + 'px';

		popup.style.top =
			Math.round(
				top
			) + 'px';
	}


	/* =========================================================
	   SHOW POPUP
	========================================================= */

	function gddShowPopup( button ) {

		var popup =
			gddCreatePopup();

		gddPositionPopup(
			button
		);

		/*
		 * Force reflow
		 */
		void popup.offsetWidth;

		popup.classList.add(
			'gdd-popup-visible'
		);
	}


	/* =========================================================
	   HIDE POPUP
	========================================================= */

	function gddHidePopup() {

		if ( ! gddPopup ) {
			return;
		}

		gddPopup.classList.remove(
			'gdd-popup-visible'
		);
	}


	/* =========================================================
	   COPY MESSAGE
	========================================================= */

	function gddShowCopyMessage() {

		var oldMessage =
			document.querySelector(
				'.gdd-copy-message'
			);

		if ( oldMessage ) {
			oldMessage.remove();
		}

		var message =
			document.createElement(
				'div'
			);

		message.className =
			'gdd-copy-message';

		message.innerHTML =
			'<span>✓</span>' +
			'<span>کد تخفیف کپی شد</span>';

		document.body.appendChild(
			message
		);

		requestAnimationFrame(
			function () {

				message.classList.add(
					'gdd-copy-visible'
				);

			}
		);


		if ( gddCopyTimer ) {

			clearTimeout(
				gddCopyTimer
			);

		}


		gddCopyTimer =
			setTimeout(
				function () {

					message.classList.remove(
						'gdd-copy-visible'
					);

					setTimeout(
						function () {

							if ( message ) {
								message.remove();
							}

						},
						250
					);

				},
				1700
			);
	}


	/* =========================================================
	   COPY TEXT
	========================================================= */

	function gddCopyText( text ) {

		/*
		 * Clipboard API
		 */
		if (
			navigator.clipboard &&
			window.isSecureContext
		) {

			return navigator.clipboard.writeText(
				text
			);

		}


		/*
		 * Fallback
		 */
		return new Promise(
			function (
				resolve,
				reject
			) {

				var textarea =
					document.createElement(
						'textarea'
					);

				textarea.value =
					text;

				textarea.setAttribute(
					'readonly',
					''
				);

				textarea.style.position =
					'fixed';

				textarea.style.left =
					'-99999px';

				textarea.style.top =
					'0';

				textarea.style.opacity =
					'0';

				document.body.appendChild(
					textarea
				);

				textarea.focus();

				textarea.select();

				try {

					var successful =
						document.execCommand(
							'copy'
						);

					textarea.remove();

					if ( successful ) {

						resolve();

					} else {

						reject();

					}

				} catch ( error ) {

					textarea.remove();

					reject(
						error
					);

				}

			}
		);
	}


	/* =========================================================
	   MOUSE ENTER
	========================================================= */

	document.addEventListener(
		'mouseenter',
		function ( event ) {

			var button =
				event.target.closest(
					'.gdd-discount-code'
				);

			if ( ! button ) {
				return;
			}

			gddShowPopup(
				button
			);

		},
		true
	);


	/* =========================================================
	   MOUSE LEAVE
	========================================================= */

	document.addEventListener(
		'mouseleave',
		function ( event ) {

			var button =
				event.target.closest(
					'.gdd-discount-code'
				);

			if ( ! button ) {
				return;
			}

			gddHidePopup();

		},
		true
	);


	/* =========================================================
	   FOCUS
	========================================================= */

	document.addEventListener(
		'focusin',
		function ( event ) {

			var button =
				event.target.closest(
					'.gdd-discount-code'
				);

			if ( ! button ) {
				return;
			}

			gddShowPopup(
				button
			);

		}
	);


	/* =========================================================
	   BLUR
	========================================================= */

	document.addEventListener(
		'focusout',
		function ( event ) {

			var button =
				event.target.closest(
					'.gdd-discount-code'
				);

			if ( ! button ) {
				return;
			}

			gddHidePopup();

		}
	);


	/* =========================================================
	   CLICK / COPY
	========================================================= */

	document.addEventListener(
		'click',
		function ( event ) {

			var button =
				event.target.closest(
					'.gdd-discount-code'
				);

			if ( ! button ) {
				return;
			}

			var code =
				button.getAttribute(
					'data-gdd-code'
				);

			if ( ! code ) {
				return;
			}

			gddCopyText(
				code
			)
			.then(
				function () {

					gddShowCopyMessage();

				}
			)
			.catch(
				function () {

					window.prompt(
						'کد تخفیف را کپی کنید:',
						code
					);

				}
			);

		}
	);


	/* =========================================================
	   RESIZE
	========================================================= */

	window.addEventListener(
		'resize',
		function () {

			if (
				gddPopup &&
				gddPopup.classList.contains(
					'gdd-popup-visible'
				)
			) {

				var active =
					document.querySelector(
						'.gdd-discount-code:hover'
					);

				if ( active ) {

					gddPositionPopup(
						active
					);

				}

			}

		}
	);


	/* =========================================================
	   SCROLL
	========================================================= */

	window.addEventListener(
		'scroll',
		function () {

			if (
				gddPopup &&
				gddPopup.classList.contains(
					'gdd-popup-visible'
				)
			) {

				var active =
					document.querySelector(
						'.gdd-discount-code:hover'
					);

				if ( active ) {

					gddPositionPopup(
						active
					);

				}

			}

		},
		true
	);

})();

JS;

		wp_add_inline_script(
			'gdd-frontend',
			$js
		);
	}

	/**
	 * =========================================================
	 * SHORTCODE
	 * =========================================================
	 */
	public function shortcode() {

		/**
		 * فقط یک متن
		 */
		$text = trim(
			get_option(
				self::TEXT_OPTION,
				''
			)
		);

		/**
		 * فقط یک کد
		 */
		$code = trim(
			get_option(
				self::CODE_OPTION,
				''
			)
		);

		/**
		 * رنگ متن
		 */
		$text_color = sanitize_hex_color(
			get_option(
				self::TEXT_COLOR_OPTION,
				'#FFFFFF'
			)
		);

		/**
		 * رنگ کد
		 */
		$code_color = sanitize_hex_color(
			get_option(
				self::CODE_COLOR_OPTION,
				'#FFFFFF'
			)
		);

		/**
		 * بکگراند کد
		 */
		$code_bg = sanitize_hex_color(
			get_option(
				self::CODE_BG_OPTION,
				'#0F6B4F'
			)
		);

		/**
		 * سایز متن
		 */
		$text_size = absint(
			get_option(
				self::TEXT_SIZE_OPTION,
				14
			)
		);

		/**
		 * سایز کد
		 */
		$code_size = absint(
			get_option(
				self::CODE_SIZE_OPTION,
				14
			)
		);

		/**
		 * ضخامت
		 */
		$border_width = absint(
			get_option(
				self::BORDER_WIDTH_OPTION,
				1
			)
		);

		/**
		 * نوع حاشیه
		 */
		$border_style = get_option(
			self::BORDER_STYLE_OPTION,
			'solid'
		);

		/**
		 * گردی
		 */
		$border_radius = absint(
			get_option(
				self::BORDER_RADIUS_OPTION,
				6
			)
		);

		/**
		 * مقادیر پیش‌فرض
		 */
		if ( ! $text_color ) {
			$text_color = '#FFFFFF';
		}

		if ( ! $code_color ) {
			$code_color = '#FFFFFF';
		}

		if ( ! $code_bg ) {
			$code_bg = '#0F6B4F';
		}

		/**
		 * استایل‌های مجاز
		 */
		$allowed_styles = array(
			'solid',
			'dashed',
			'dotted',
		);

		if (
			! in_array(
				$border_style,
				$allowed_styles,
				true
			)
		) {

			$border_style =
				'solid';

		}

		/**
		 * محدودیت‌ها
		 */
		$text_size = min(
			max(
				$text_size,
				8
			),
			60
		);

		$code_size = min(
			max(
				$code_size,
				8
			),
			60
		);

		$border_width = min(
			max(
				$border_width,
				0
			),
			10
		);

		$border_radius = min(
			max(
				$border_radius,
				0
			),
			50
		);

		/**
		 * اگر هیچ اطلاعاتی وجود نداشته باشد
		 */
		if (
			empty( $text ) &&
			empty( $code )
		) {

			return '';

		}

		ob_start();

		?>

		<div
			class="gdd-discount-root"

			style="
				--gdd-text-color: <?php echo esc_attr( $text_color ); ?>;
				--gdd-code-color: <?php echo esc_attr( $code_color ); ?>;
				--gdd-code-bg: <?php echo esc_attr( $code_bg ); ?>;
				--gdd-text-size: <?php echo esc_attr( $text_size ); ?>px;
				--gdd-code-size: <?php echo esc_attr( $code_size ); ?>px;
				--gdd-border-width: <?php echo esc_attr( $border_width ); ?>px;
				--gdd-border-style: <?php echo esc_attr( $border_style ); ?>;
				--gdd-border-radius: <?php echo esc_attr( $border_radius ); ?>px;
			"
		>

			<div class="gdd-discount-content">

				<!-- =================================================
				     TEXT
				================================================= -->

				<?php if ( ! empty( $text ) ) : ?>

					<span class="gdd-discount-text">

						<?php
						echo esc_html(
							$text
						);
						?>

					</span>

				<?php endif; ?>


				<!-- =================================================
				     SEPARATOR
				================================================= -->

				<?php if (
					! empty( $text ) &&
					! empty( $code )
				) : ?>

					<span
						class="gdd-discount-separator"
						aria-hidden="true"
					>
						|
					</span>

				<?php endif; ?>


				<!-- =================================================
				     CODE LABEL
				================================================= -->

				<?php if ( ! empty( $code ) ) : ?>

					<span class="gdd-discount-label">

						کد تخفیف :

					</span>


					<!-- =================================================
					     CLICKABLE CODE
					================================================= -->

					<button
						type="button"
						class="gdd-discount-code"

						data-gdd-code="<?php echo esc_attr( $code ); ?>"

						aria-label="کپی کد تخفیف"
					>

						<?php
						echo esc_html(
							$code
						);
						?>

					</button>

				<?php endif; ?>

			</div>

		</div>

		<?php

		return ob_get_clean();
	}

	/**
	 * =========================================================
	 * ADMIN ASSETS
	 * =========================================================
	 */
	public function admin_assets( $hook ) {

		if (
			'toplevel_page_gdd-daily-discount' !== $hook
		) {
			return;
		}

		/**
		 * =====================================================
		 * ADMIN CSS
		 * =====================================================
		 */

		wp_register_style(
			'gdd-admin',
			false,
			array(),
			self::VERSION
		);

		wp_enqueue_style(
			'gdd-admin'
		);

		$css = <<<'CSS'

/* =========================================================
   ADMIN
========================================================= */

.gdd-admin-wrap {

	max-width:
		1120px;

	margin:
		25px 20px 40px 0;

	direction:
		rtl;
}


/* =========================================================
   HEADER
========================================================= */

.gdd-admin-head {

	display:
		flex;

	align-items:
		center;

	justify-content:
		space-between;

	gap:
		20px;

	margin-bottom:
		20px;
}

.gdd-admin-head-content {

	display:
		flex;

	align-items:
		center;

	gap:
		12px;
}

.gdd-admin-logo {

	width:
		44px;

	height:
		44px;

	display:
		flex;

	align-items:
		center;

	justify-content:
		center;

	border-radius:
		10px;

	background:
		#111827;

	color:
		#ffffff;
}

.gdd-admin-logo .dashicons {

	font-size:
		21px;

	width:
		21px;

	height:
		21px;
}

.gdd-admin-head h1 {

	margin:
		0 0 4px;

	font-size:
		24px;

	font-weight:
		700;
}

.gdd-admin-head p {

	margin:
		0;

	color:
		#64748b;

	font-size:
		12px;
}


/* =========================================================
   STATUS
========================================================= */

.gdd-admin-status {

	display:
		flex;

	align-items:
		center;

	gap:
		7px;

	padding:
		6px 11px;

	border-radius:
		20px;

	background:
		#f0fdf4;

	color:
		#166534;

	font-size:
		12px;
}

.gdd-admin-status span {

	width:
		7px;

	height:
		7px;

	border-radius:
		50%;

	background:
		#22c55e;
}


/* =========================================================
   SUCCESS
========================================================= */

.gdd-admin-success {

	display:
		flex;

	align-items:
		center;

	gap:
		7px;

	margin-bottom:
		18px;

	padding:
		11px 14px;

	border-right:
		3px solid #22c55e;

	border-radius:
		7px;

	background:
		#f0fdf4;

	color:
		#166534;

	font-size:
		13px;
}


/* =========================================================
   GRID
========================================================= */

.gdd-admin-grid {

	display:
		grid;

	grid-template-columns:
		minmax(0, 1.35fr)
		minmax(300px, 1fr);

	gap:
		18px;
}


/* =========================================================
   CARD
========================================================= */

.gdd-admin-card {

	background:
		#ffffff;

	border:
		1px solid #e5e7eb;

	border-radius:
		12px;

	padding:
		22px;

	box-shadow:
		0 2px 8px
		rgba(15,23,42,.04);
}

.gdd-main-card {

	grid-row:
		span 2;
}


/* =========================================================
   CARD HEADING
========================================================= */

.gdd-card-heading {

	display:
		flex;

	align-items:
		center;

	gap:
		11px;

	margin-bottom:
		20px;
}

.gdd-card-icon {

	width:
		38px;

	height:
		38px;

	display:
		flex;

	align-items:
		center;

	justify-content:
		center;

	border:
		1px solid #e5e7eb;

	border-radius:
		8px;

	background:
		#f8fafc;

	color:
		#475569;
}

.gdd-card-heading h2 {

	margin:
		0 0 3px;

	font-size:
		15px;

	font-weight:
		700;

	color:
		#111827;
}

.gdd-card-heading p {

	margin:
		0;

	font-size:
		11px;

	color:
		#64748b;
}


/* =========================================================
   FIELDS
========================================================= */

.gdd-field {

	margin-bottom:
		18px;
}

.gdd-field label,
.gdd-setting label {

	display:
		block;

	margin-bottom:
		7px;

	font-size:
		13px;

	font-weight:
		600;

	color:
		#111827;
}

.gdd-field textarea,
.gdd-field input[type="text"],
.gdd-setting select {

	width:
		100%;

	box-sizing:
		border-box;

	padding:
		10px 12px;

	border:
		1px solid #dbe2ea;

	border-radius:
		8px;

	background:
		#ffffff;

	font-size:
		13px;

	box-shadow:
		none;
}

.gdd-field textarea {

	min-height:
		110px;

	resize:
		vertical;

	line-height:
		1.8;
}

.gdd-field textarea:focus,
.gdd-field input[type="text"]:focus,
.gdd-setting select:focus {

	border-color:
		#94a3b8;

	box-shadow:
		0 0 0 2px
		rgba(148,163,184,.12);

	outline:
		none;
}

.gdd-field-help {

	margin-top:
		5px;

	color:
		#94a3b8;

	font-size:
		11px;
}


/* =========================================================
   SECTION
========================================================= */

.gdd-section-title {

	display:
		flex;

	align-items:
		center;

	margin:
		25px 0 15px;

	padding-bottom:
		9px;

	border-bottom:
		1px solid #eef2f7;

	color:
		#111827;

	font-size:
		13px;

	font-weight:
		700;
}


/* =========================================================
   SETTINGS
========================================================= */

.gdd-settings-grid {

	display:
		grid;

	grid-template-columns:
		1fr 1fr;

	gap:
		16px;
}

.gdd-setting {

	min-width:
		0;
}


/* =========================================================
   COLORS
========================================================= */

.gdd-color-control {

	display:
		flex;

	align-items:
		center;

	gap:
		7px;
}

.gdd-color-control input[type="color"] {

	width:
		45px;

	height:
		40px;

	padding:
		3px;

	border:
		1px solid #dbe2ea;

	border-radius:
		7px;

	background:
		#ffffff;

	cursor:
		pointer;
}

.gdd-color-value {

	direction:
		ltr;

	text-align:
		left;
}


/* =========================================================
   RANGE
========================================================= */

.gdd-range-row {

	display:
		flex;

	align-items:
		center;

	gap:
		9px;
}

.gdd-range-row input[type="range"] {

	flex:
		1;

	min-width:
		0;
}

.gdd-range-row strong {

	min-width:
		47px;

	padding:
		6px 7px;

	border:
		1px solid #e5e7eb;

	border-radius:
		6px;

	background:
		#f8fafc;

	color:
		#475569;

	font-size:
		11px;

	text-align:
		center;
}


/* =========================================================
   FOOTER
========================================================= */

.gdd-form-footer {

	margin-top:
		22px;

	padding-top:
		17px;

	border-top:
		1px solid #eef2f7;
}


/* =========================================================
   SAVE BUTTON
========================================================= */

.gdd-save-button {

	display:
		inline-flex;

	align-items:
		center;

	justify-content:
		center;

	gap:
		7px;

	min-width:
		135px;

	height:
		38px;

	padding:
		0 15px;

	border:
		0;

	border-radius:
		7px;

	background:
		#2271b1;

	color:
		#ffffff;

	cursor:
		pointer;

	font-size:
		13px;
}

.gdd-save-button:hover {

	background:
		#135e96;
}


/* =========================================================
   PREVIEW
========================================================= */

.gdd-preview-area {

	display:
		flex;

	align-items:
		center;

	justify-content:
		center;

	min-height:
		110px;

	padding:
		20px;

	border:
		1px dashed #dbe2ea;

	border-radius:
		9px;

	overflow:
		visible;
}

.gdd-preview-content {

	display:
		inline-flex;

	align-items:
		center;

	justify-content:
		center;

	flex-wrap:
		wrap;

	gap:
		7px;

	font-family:
		inherit;

	direction:
		rtl;
}

.gdd-preview-text {

	font-size:
		var(--gdd-text-size);

	color:
		var(--gdd-text-color);

	line-height:
		1.35;
}

.gdd-preview-separator {

	display:
		inline-flex;

	color:
		var(--gdd-text-color);

	font-size:
		var(--gdd-text-size);

	line-height:
		1;

	opacity:
		.75;
}

.gdd-preview-label {

	display:
		inline-flex;

	color:
		var(--gdd-text-color);

	font-size:
		var(--gdd-text-size);

	line-height:
		1.35;

	white-space:
		nowrap;
}

.gdd-preview-code {

	display:
		inline-flex;

	align-items:
		center;

	justify-content:
		center;

	padding:
		3px 10px;

	background:
		var(--gdd-code-bg);

	border:
		var(--gdd-border-width)
		var(--gdd-border-style)
		var(--gdd-code-color);

	border-radius:
		var(--gdd-border-radius);

	color:
		var(--gdd-code-color);

	font-size:
		var(--gdd-code-size);

	font-weight:
		700;

	line-height:
		1.2;

	white-space:
		nowrap;
}

.gdd-preview-note {

	margin-top:
		10px;

	color:
		#94a3b8;

	font-size:
		11px;

	text-align:
		center;
}


/* =========================================================
   SHORTCODE
========================================================= */

.gdd-shortcode-box {

	display:
		flex;

	align-items:
		center;

	gap:
		8px;
}

.gdd-shortcode-box code {

	flex:
		1;

	padding:
		9px 10px;

	border:
		1px solid #e5e7eb;

	border-radius:
		7px;

	background:
		#f8fafc;

	direction:
		ltr;

	text-align:
		left;

	font-size:
		12px;
}

.gdd-copy-shortcode {

	height:
		36px;

	padding:
		0 13px;

	border:
		1px solid #d1d5db;

	border-radius:
		7px;

	background:
		#ffffff;

	cursor:
		pointer;

	font-size:
		12px;
}

.gdd-copy-shortcode:hover {

	background:
		#f8fafc;
}


/* =========================================================
   MOBILE ADMIN
========================================================= */

@media (max-width: 782px) {

	.gdd-admin-wrap {

		margin-right:
			10px;

		margin-left:
			10px;
	}

	.gdd-admin-grid,
	.gdd-settings-grid {

		grid-template-columns:
			1fr;
	}

	.gdd-main-card {

		grid-row:
			auto;
	}

	.gdd-admin-head {

		align-items:
			flex-start;
	}

}

CSS;

		wp_add_inline_style(
			'gdd-admin',
			$css
		);

		/**
		 * =====================================================
		 * ADMIN JS
		 * =====================================================
		 */

		wp_register_script(
			'gdd-admin',
			false,
			array(),
			self::VERSION,
			true
		);

		wp_enqueue_script(
			'gdd-admin'
		);

		$js = <<<'JS'

(function () {

	'use strict';


	/* =========================================================
	   RANGE
	========================================================= */

	function gddBindRange(
		id,
		outputId,
		cssVariable
	) {

		var input =
			document.getElementById(
				id
			);

		var output =
			document.getElementById(
				outputId
			);

		var preview =
			document.getElementById(
				'gdd-live-preview'
			);

		if (
			! input ||
			! output ||
			! preview
		) {
			return;
		}

		input.addEventListener(
			'input',
			function () {

				output.textContent =
					input.value +
					'px';

				preview.style.setProperty(
					cssVariable,
					input.value +
					'px'
				);

			}
		);
	}


	gddBindRange(
		'gdd_text_size',
		'gdd_text_size_value',
		'--gdd-text-size'
	);


	gddBindRange(
		'gdd_code_size',
		'gdd_code_size_value',
		'--gdd-code-size'
	);


	gddBindRange(
		'gdd_border_width',
		'gdd_border_width_value',
		'--gdd-border-width'
	);


	gddBindRange(
		'gdd_border_radius',
		'gdd_border_radius_value',
		'--gdd-border-radius'
	);


	/* =========================================================
	   COLOR
	========================================================= */

	function gddBindColor(
		id,
		cssVariable
	) {

		var input =
			document.getElementById(
				id
			);

		var preview =
			document.getElementById(
				'gdd-live-preview'
			);

		if (
			! input ||
			! preview
		) {
			return;
		}

		var text =
			input.parentNode.querySelector(
				'.gdd-color-value'
			);

		input.addEventListener(
			'input',
			function () {

				if ( text ) {

					text.value =
						input.value;

				}

				preview.style.setProperty(
					cssVariable,
					input.value
				);

			}
		);
	}


	gddBindColor(
		'gdd_text_color',
		'--gdd-text-color'
	);


	gddBindColor(
		'gdd_code_color',
		'--gdd-code-color'
	);


	gddBindColor(
		'gdd_code_bg',
		'--gdd-code-bg'
	);


	/* =========================================================
	   BORDER STYLE
	========================================================= */

	var borderStyle =
		document.getElementById(
			'gdd_border_style'
		);

	var preview =
		document.getElementById(
			'gdd-live-preview'
		);

	if (
		borderStyle &&
		preview
	) {

		borderStyle.addEventListener(
			'change',
			function () {

				preview.style.setProperty(
					'--gdd-border-style',
					borderStyle.value
				);

			}
		);

	}


	/* =========================================================
	   LIVE TEXT
	========================================================= */

	var textInput =
		document.getElementById(
			'gdd_text'
		);

	var previewText =
		document.getElementById(
			'gdd-preview-text'
		);

	if (
		textInput &&
		previewText
	) {

		textInput.addEventListener(
			'input',
			function () {

				previewText.textContent =
					textInput.value ||
					'تخفیف امروز 20% برای خرید بالای 2 میلیون تومان';

			}
		);

	}


	/* =========================================================
	   LIVE CODE
	========================================================= */

	var codeInput =
		document.getElementById(
			'gdd_code'
		);

	var previewCode =
		document.getElementById(
			'gdd-preview-code'
		);

	if (
		codeInput &&
		previewCode
	) {

		codeInput.addEventListener(
			'input',
			function () {

				previewCode.textContent =
					codeInput.value ||
					'T20';

			}
		);

	}


	/* =========================================================
	   COPY SHORTCODE
	========================================================= */

	document.addEventListener(
		'click',
		function (event) {

			var button =
				event.target.closest(
					'.gdd-copy-shortcode'
				);

			if ( ! button ) {
				return;
			}

			var value =
				button.getAttribute(
					'data-gdd-copy'
				);

			if ( ! value ) {
				return;
			}

			function success() {

				var oldText =
					button.textContent;

				button.textContent =
					'کپی شد';

				setTimeout(
					function () {

						button.textContent =
							oldText;

					},
					1200
				);
			}


			if (
				navigator.clipboard &&
				window.isSecureContext
			) {

				navigator.clipboard
					.writeText(
						value
					)
					.then(
						success
					);

			} else {

				var textarea =
					document.createElement(
						'textarea'
					);

				textarea.value =
					value;

				textarea.style.position =
					'fixed';

				textarea.style.left =
					'-99999px';

				document.body.appendChild(
					textarea
				);

				textarea.select();

				try {

					document.execCommand(
						'copy'
					);

					success();

				} catch ( error ) {}

				textarea.remove();

			}

		}
	);

})();

JS;

		wp_add_inline_script(
			'gdd-admin',
			$js
		);
	}
}


/**
 * =========================================================
 * START PLUGIN
 * =========================================================
 */

new Gildata_Daily_Discount();

افزونه تخفیف روز وردپرس؛ نمایش حرفه‌ای کد تخفیف با قابلیت کپی

افزونه تخفیف روز یک ابزار وردپرسی برای نمایش متن تخفیف و کد تخفیف در بخش‌های مختلف سایت است. این افزونه امکان مدیریت محتوای تخفیف، شخصی‌سازی ظاهر کد و استفاده از شورت‌کد را فراهم می‌کند و در سمت کاربر نیز قابلیت کپی کردن کد تخفیف با کلیک روی آن وجود دارد.

این افزونه در نسخه 1.5.0 ارائه شده و برای WordPress حداقل نسخه 5.8 و PHP نسخه 7.4 طراحی شده است.

افزونه تخفیف روز چه کاری انجام می‌دهد؟

هدف اصلی افزونه، نمایش یک پیام تخفیف به همراه یک کد قابل کپی در سایت است. مدیر سایت می‌تواند متن تخفیف و کد موردنظر را از پنل اختصاصی افزونه وارد کند.

در ساختار افزونه، برای متن تخفیف، کد تخفیف، رنگ متن، رنگ کد، رنگ پس‌زمینه کد، اندازه متن، اندازه کد، ضخامت حاشیه، نوع حاشیه و میزان گردی گوشه‌ها تنظیمات جداگانه در نظر گرفته شده است.

مدیریت تخفیف از پنل وردپرس

افزونه یک منوی اختصاصی با عنوان «تخفیف روز» در پنل مدیریت وردپرس ایجاد می‌کند. این بخش برای مدیریت متن، کد تخفیف و تنظیمات ظاهری مورد استفاده قرار می‌گیرد.

در بخش مدیریت، امکان وارد کردن متن تخفیف و کد تخفیف وجود دارد. متن تخفیف از طریق فیلد متنی و کد تخفیف از طریق فیلد مخصوص کد دریافت می‌شود.

تنظیم رنگ و ظاهر کد تخفیف

یکی از امکانات مهم افزونه، شخصی‌سازی ظاهر کد تخفیف است. مدیر سایت می‌تواند رنگ متن، رنگ نوشته کد و رنگ پس‌زمینه کد را تنظیم کند. این مقادیر قبل از ذخیره نیز اعتبارسنجی می‌شوند تا رنگ‌های نامعتبر وارد تنظیمات نشوند.

همچنین اندازه متن و اندازه کد تخفیف قابل تنظیم است. اندازه هر دو بخش بین 8 تا 60 پیکسل محدود شده است. ضخامت حاشیه نیز بین صفر تا 10 پیکسل و میزان گردی گوشه‌ها بین صفر تا 50 پیکسل کنترل می‌شود.

انتخاب نوع حاشیه کد

برای حاشیه کد تخفیف سه حالت در نظر گرفته شده است:

  • حاشیه ساده یا Solid
  • حاشیه خط‌چین یا Dashed
  • حاشیه نقطه‌ای یا Dotted

در صورت ارسال مقدار نامعتبر، افزونه به‌صورت پیش‌فرض از حالت Solid استفاده می‌کند.

پیش‌نمایش زنده تنظیمات

افزونه در پنل مدیریت دارای بخش «پیش‌نمایش» است. این بخش ظاهر متن و کد تخفیف را با تنظیمات فعلی نمایش می‌دهد و متغیرهای CSS مربوط به رنگ، اندازه، ضخامت حاشیه، نوع حاشیه و گردی گوشه‌ها را به‌صورت مستقیم روی پیش‌نمایش اعمال می‌کند.

این قابلیت باعث می‌شود مدیر سایت قبل از استفاده از کد تخفیف در سایت، ظاهر آن را مشاهده کند.

کپی کد تخفیف با یک کلیک

کد تخفیف در بخش کاربری سایت به شکل یک دکمه قابل کلیک نمایش داده می‌شود. هنگام کلیک، مقدار کد دریافت شده و عملیات کپی با Clipboard API انجام می‌شود. در مرورگرهایی که Clipboard API در دسترس نباشد، افزونه از روش جایگزین برای کپی کردن متن استفاده می‌کند.

پس از کپی موفق، پیام «کد تخفیف کپی شد» به کاربر نمایش داده می‌شود. این پیام به‌صورت موقت ظاهر شده و سپس از صفحه حذف می‌شود.

Popup راهنمای کپی کد

هنگام قرار گرفتن نشانگر روی کد تخفیف، Popup راهنمای «برای کپی کردن کلیک کنید» نمایش داده می‌شود. Popup به‌صورت مستقیم داخل body قرار می‌گیرد تا توسط ساختارهایی مانند Elementor یا overflow:hidden بریده نشود.

سیستم موقعیت‌دهی Popup نیز تلاش می‌کند آن را در محدوده قابل مشاهده مرورگر نگه دارد. اگر بالای دکمه فضای کافی وجود نداشته باشد، Popup به قسمت پایین منتقل می‌شود.

طراحی واکنش‌گرا برای موبایل

CSS افزونه برای نمایش در موبایل نیز تنظیم شده است. در عرض‌های کمتر از 600 پیکسل، فاصله بین اجزای تخفیف کاهش پیدا می‌کند و اندازه Popup و فاصله داخلی کد نیز متناسب با صفحه موبایل تنظیم می‌شود.

نمایش بدون ایجاد پس‌زمینه برای کل بخش

ساختار اصلی نمایش تخفیف به‌صورت inline-flex طراحی شده و پس‌زمینه کل بخش شفاف است. در نتیجه، ظاهر اصلی فقط روی بخش‌های مربوط به متن و کد تخفیف اعمال می‌شود و کل ناحیه یک باکس بزرگ ایجاد نمی‌کند.

کد تخفیف به‌صورت یک دکمه جمع‌وجور با حاشیه قابل تنظیم، گوشه‌های گرد، افکت Hover و حالت Active طراحی شده است.

استفاده از شورت‌کد افزونه

برای نمایش تخفیف در سایت، افزونه شورت‌کد زیر را ارائه می‌کند:

[daily_discount]

این شورت‌کد را می‌توان در Elementor یا سایر بخش‌هایی که از شورت‌کدهای وردپرس پشتیبانی می‌کنند استفاده کرد.

هنگام اجرای شورت‌کد، تنظیمات ذخیره‌شده شامل متن، کد، رنگ‌ها، اندازه‌ها و تنظیمات حاشیه دریافت شده و روی خروجی اعمال می‌شوند.

ساختار نمایش در سایت

اگر متن تخفیف وجود داشته باشد، متن نمایش داده می‌شود. در صورتی که هم متن و هم کد وجود داشته باشند، بین آن‌ها علامت | قرار می‌گیرد و سپس عبارت «کد تخفیف :» همراه با کد قابل کلیک نمایش داده می‌شود.

اگر هیچ متن یا کدی ذخیره نشده باشد، شورت‌کد خروجی تولید نمی‌کند و مقدار خالی برمی‌گرداند.

امنیت و اعتبارسنجی اطلاعات

در بخش ذخیره تنظیمات، افزونه از Nonce برای اعتبارسنجی درخواست استفاده می‌کند. همچنین برای ورودی‌های مختلف از توابع Sanitization وردپرس مانند sanitize_text_field، sanitize_textarea_field، sanitize_hex_color و sanitize_key استفاده شده است.

برای رنگ‌ها نیز در صورت نامعتبر بودن مقدار، رنگ پیش‌فرض جایگزین می‌شود. همچنین مقادیر عددی مانند اندازه متن، اندازه کد، ضخامت حاشیه و Radius در محدوده مشخص نگه داشته می‌شوند.

جمع‌بندی

افزونه «تخفیف روز» یک ابزار ساده و کاربردی برای نمایش کدهای تخفیف در سایت وردپرسی است. مدیریت متن و کد، تنظیم رنگ و اندازه، شخصی‌سازی حاشیه، پیش‌نمایش، نمایش واکنش‌گرا، Popup راهنما و امکان کپی کد با یک کلیک، مهم‌ترین قابلیت‌های پیاده‌سازی‌شده در این افزونه هستند.

استفاده از شورت‌کد [daily_discount] نیز باعث می‌شود نمایش این بخش در صفحات و بخش‌های مختلف سایت، از جمله محیط‌هایی مانند Elementor، ساده باشد.