=== ServisPin ===
Contributors: officialwebfoo
Tags: woocommerce, delivery, pincode, shipping, estimator
Requires at least: 5.8
Tested up to: 7.0
Requires PHP: 7.4
Stable tag: 1.7.7
License: GPL-2.0-or-later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

Let customers check estimated delivery dates for their pincode with WooCommerce AJAX lookup, CSV tools, shortcodes, and a persistent delivery bar.

== Description ==

ServisPin lets customers enter their pincode and instantly see an estimated delivery date for their location — without leaving the page.

A shopper types a 6-digit pincode, the plugin looks it up over AJAX against a database you manage, and shows the delivery estimate (plus an optional expected date, express-delivery badge, and COD/Prepaid availability) right where they're shopping. It's built for WooCommerce, with AJAX lookup, admin pincode management, CSV bulk import/export, shortcodes, and a persistent delivery bar that remembers a customer's pincode as they browse.

**WooCommerce is optional.** The shortcodes, admin panel, AJAX lookup, delivery bar, and CSV tools all work on any WordPress site with no WooCommerce dependency. WooCommerce is only used for one specific feature — an optional compact checker that can appear directly on single product pages — which simply doesn't appear if WooCommerce isn't installed, with no errors or broken functionality either way.

== Features ==

* Pincode delivery lookup over AJAX — no page reload.
* Estimated delivery dates, calculated from your delivery-days data and a configurable daily order-cutoff time (e.g. "Order before 5 PM today to get it by Fri, 14 Aug").
* WooCommerce integration: an optional compact checker on single product pages, alongside the standard shortcodes.
* Admin pincode management: add, edit, activate/deactivate, search, filter and bulk-manage pincodes from a dedicated screen.
* CSV bulk import with duplicate detection and an import summary, plus a downloadable sample CSV template that matches the importer's exact column format.
* CSV export of your full pincode list.
* Shortcodes: `[pincode_delivery_estimator]` (the full checker widget, also available in a compact style) and `[pincode_delivery_message]` (a small "Check your delivery date" prompt, or the customer's last result once they've checked).
* A "Check Now" popup for looking up or changing a pincode from anywhere on the site.
* A persistent delivery bar that remembers the customer's pincode and estimated delivery as they browse, with its own "Change Pincode" option that reopens the popup.
* Same-Day / Express Delivery and COD/Prepaid availability badges, settable per pincode.
* A custom, indexed database table so lookups stay fast even with a large pincode list.
* Fully namespaced CSS (a `.pde-` prefix throughout) so the plugin's styles don't clash with your theme or other plugins.
* Nonces, capability checks, sanitized input, escaped output, and prepared SQL queries throughout; a lightweight rate limit on the public lookup endpoint to reduce automated abuse.
* Uninstall data removal is opt-in — nothing is deleted unless you explicitly turn that on in Settings.

== Installation ==

1. Go to Plugins → Add New in your WordPress dashboard.
2. Search for "ServisPin".
3. Install and activate ServisPin.
4. Open **ServisPin → Add Pincode** to add your delivery data manually, or **ServisPin → Bulk Upload** to import it from a CSV file (a sample template is available on that screen).
5. Visit **ServisPin → Settings** to configure the checker's text, colors, the persistent delivery bar, and order-cutoff/express-delivery options.
6. Add the `[pincode_delivery_estimator]` shortcode to any page, post, or shortcode-compatible page builder block where you want the checker to appear — or use `[pincode_delivery_message]` for a smaller "Check your delivery date" prompt.
7. On a WooCommerce store, optionally enable the compact checker on product pages from Settings.
8. Test a pincode lookup as a customer would, to confirm your delivery data and messaging look right.

== Frequently Asked Questions ==

= Does ServisPin work with WooCommerce? =

WooCommerce is not required — the shortcodes, admin panel, AJAX lookup, and delivery bar all work on any WordPress site without it. When WooCommerce is active, ServisPin can additionally show a compact delivery checker directly on single product pages (via the `woocommerce_single_product_summary` hook), toggleable from Settings.

= Can I import pincode data in bulk? =

Yes, via **ServisPin → Bulk Upload**. Upload a CSV with `pincode` and `delivery_days` columns (optionally `city`, `state`, `express_available`); existing pincodes are updated, new ones are added, and you get an import summary (total, added, updated, invalid/skipped rows).

= Can I download a sample CSV? =

Yes. The Bulk Upload screen has a "Download Sample CSV Template" button that generates a CSV using the exact column headers the importer expects, with a few example rows, so you can fill it in and re-upload it directly.

= Can I export pincode data? =

Yes, from **ServisPin → Import/Export**, as a CSV containing all your pincode records.

= Does ServisPin support AJAX lookup? =

Yes. The customer-facing checker (in the shortcode widget, the "Check Now" popup, and the product-page checker) looks up a pincode over AJAX and shows the result without reloading the page. The pincode is validated and sanitized server-side regardless of what the browser sends.

= Can customers change their pincode? =

Yes. Once a customer has checked a pincode, a "Change" link (in the message shortcode and the persistent delivery bar) reopens the same popup so they can look up a different one. The last checked pincode is also remembered (via the browser's local storage) and automatically re-verified on the next page load.

= Does ServisPin support shortcodes? =

Yes, two: `[pincode_delivery_estimator]` (the full checker widget; add `style="compact"` for a smaller version) and `[pincode_delivery_message]` (a compact "Check your delivery date" prompt/result).

= Can I use ServisPin with Elementor? =

Yes. Both shortcodes render through WordPress's standard shortcode mechanism, so they work inside Elementor's Shortcode widget the same way any other shortcode does.

= Can I use ServisPin with Gutenberg? =

Yes, via the core Shortcode block, for the same reason — no special integration is required.

= Does uninstalling ServisPin delete my data? =

No, not unless you explicitly opt in. Under **ServisPin → Settings**, "Delete Data on Uninstall" is OFF by default — your pincode table and settings are preserved unless you turn that on before deleting the plugin. When you do delete the plugin from the Plugins screen, you'll also see an optional, skippable feedback prompt — it never blocks deletion and is never sent unless you choose to submit it.

= Is the public pincode-lookup endpoint safe from abuse? =

The lookup endpoint is intentionally public (customers aren't logged in when checking delivery). It validates and sanitizes the pincode server-side, verifies a nonce, and applies a lightweight per-IP rate limit to reduce scripted abuse without affecting normal shoppers.

== Privacy ==

ServisPin does not send your customers' pincode lookups, delivery data, or any store data to any external server. All pincode lookups are handled entirely by your own WordPress site's database and AJAX endpoint — nothing about what a customer searches for leaves your site.

**Rate limiting.** To reduce scripted abuse of the public pincode-lookup endpoint, the plugin temporarily hashes (MD5) the visitor's IP address and uses that hash as a counter key in a short-lived WordPress transient (auto-expires after 60 seconds). The raw IP address itself is never stored, never logged, and never transmitted anywhere — only the hash-based counter exists, and only for one minute.

**Uninstall feedback (fully optional).** When an administrator deletes ServisPin from the Plugins screen, an optional feedback popup appears. Nothing is sent unless the administrator explicitly clicks "Submit Feedback" — clicking "Skip & Uninstall" (or simply not submitting) sends nothing at all. If feedback is submitted, it is emailed via WordPress's native `wp_mail()` to the developer (webfoo.in@gmail.com) and contains only: the selected reason, the typed feedback text, the plugin version, the WordPress version, the PHP version, and the date/time. It never includes the site's URL, the administrator's identity or email address, IP addresses, cookies, or any authentication data.

**Local storage.** To remember a customer's last-checked pincode between page loads, the frontend widget stores that pincode and its delivery result in the visitor's own browser (via `localStorage`). This data stays on the visitor's device — it is not a cookie, and it is not sent to or stored on the server beyond the normal AJAX lookup that produced it.

== External Services ==

ServisPin does not load any external service, font, API, analytics, or tracking script anywhere in the plugin. All CSS, JavaScript, and fonts are bundled locally and served from your own site — nothing is fetched from Google, a CDN, or any other third-party domain. (Earlier versions loaded the "Poppins" font from Google Fonts for the frontend widget; this has been replaced with the operating system's own font, so no such request is made anymore.)

== Screenshots ==

1. Frontend pincode checker widget.
2. Delivery result — estimated date, express and COD/Prepaid badges.
3. The "Check Now" popup.
4. The persistent delivery bar.
5. Admin — pincode management (list, search, filters, bulk actions).
6. Admin — Bulk CSV upload, with the sample template download and import summary.
7. Admin — Settings screen.

== Changelog ==

= 1.7.7 =
* Removed the Google Fonts (Poppins) request that loaded automatically whenever the frontend widget, delivery bar, or modal rendered. The frontend now uses the visitor's operating-system font instead, so nothing is fetched from fonts.googleapis.com or any other third-party host.

= 1.7.6 =
* Renamed remaining "pde-" admin page slugs and "pde_" query-string flags to "servispin-"/"servispin_" (WordPress.org review). Old bookmarked "pde-*" admin URLs redirect automatically to the new ones.

= 1.7.5 =
* Fixed 5 Plugin Check errors: added missing `/* translators: */` comments for `%d` placeholders in the CSV import summary and export panel.
* Addressed Plugin Check's "nonce verification recommended" warnings on read-only search/filter/sort/pagination parameters and other display-only reads, with explanatory comments confirming each one — every action that actually reads, writes, or deletes data was already nonce-verified.

= 1.7.4 =
* Fixed the Bulk Upload CSV dropzone: it was styled to look like a drag-and-drop area, but had no actual drag/drop handling — dropping a file onto it did nothing. Dragging and dropping a CSV file now works, with visual feedback while dragging and the chosen file's name shown once dropped or selected.

= 1.7.3 =
* Dashboard now shows the new `[servispin_delivery_estimator]` / `[servispin_delivery_message]` shortcodes as the primary ones, with a note that the older `[pincode_delivery_estimator]` / `[pincode_delivery_message]` names still work for existing content.

= 1.7.2 =
* Fixed the CSV bulk-upload summary undercounting failures: if a database-level update genuinely failed during import, the row was still counted as "Updated" instead of "Invalid / Skipped".

= 1.7.1 =
* Fixed a bug introduced in 1.7.0: the Settings, Add/Edit Pincode, and Bulk Upload (CSV) form submit buttons were still named `pde_save_settings` / `pde_save_pincode` / `pde_bulk_upload`, but the save handler was checking for the new `servispin_*` names. This meant nothing typed on those three forms was ever saved — no error was shown, it just silently didn't take effect. Deleting and toggling status (which use link-based actions, not these forms) were unaffected. All three buttons now match the handler and save correctly.
* Removed the manual `load_plugin_textdomain()` call. WordPress.org-hosted plugins have had their translations auto-loaded since WP 4.6, so the call was redundant (per WordPress.org Plugin Check).
* Renamed the two remaining generic error codes (`pde_duplicate`, `pde_db_error`) to `servispin_duplicate` / `servispin_db_error` for full identifier-prefix consistency.

= 1.7.0 =
* Internal code-quality/compliance update: migrated the plugin's internal PHP prefix from the too-short `PDE`/`pde` to the unique `ServisPin`/`servispin` (classes, constants, the global bootstrap function, AJAX actions, hooks, nonces, the settings group, and script/style handles). This addresses WordPress.org Plugin Check's "prefix too short" requirement.
* Added new, uniquely prefixed shortcodes `[servispin_delivery_estimator]` and `[servispin_delivery_message]`. The original `[pincode_delivery_estimator]` and `[pincode_delivery_message]` continue to work unchanged for existing content.
* Existing installs are migrated automatically and safely: saved settings, last-import date, and a visitor's last-checked pincode (stored in their browser) all carry over to the new internal names the first time the updated plugin runs — nothing is lost, and the migration only runs once.
* No functional, behavioral, or UI changes. CSS class names, the database table name, and admin page URLs are unchanged in this release — see readme/plugin comments for why.

= 1.6.3 =
* Redesigned the ServisPin → Bulk Upload page: numbered step cards, a "Template Columns" reference box, and a "Requirements" sidebar. This is a visual/UI change only — the upload form, file input, nonce, sample-CSV download, and import logic are all unchanged. (The Requirements box now correctly shows the real 10MB file-size limit already enforced by the importer.)

= 1.6.2 =
* Redesigned the ServisPin → Dashboard page: icon-badged stat cards, a version badge next to the title, and restyled quick-action buttons and shortcode chips. This is a visual/UI change only — every statistic, link, and shortcode still comes from the exact same data/logic as before.

= 1.6.1 =
* Redesigned the ServisPin → Settings page into a dashboard-style layout: card-grouped sections, toggle switches, and selectable Design 1/2 cards. This is a visual/UI change only — every setting keeps its original name, default value, and save behavior; nothing was renamed, removed, or restructured in the database.

= 1.6.0 =
* Added a second frontend widget design ("Design 2") as an optional alternative — selectable from ServisPin → Settings → Design. Design 2 groups the delivery result into a tinted panel with divider lines and an accent bar, instead of Design 1's connected-circle timeline.
* Design 1 (the original layout) is unchanged and remains the default — existing sites keep looking exactly as before after updating; no action is required.
* Both designs share the exact same AJAX lookup, delivery-date calculation, validation, loading/error handling, and admin color settings — only the presentation differs.

= 1.5.0 =
* Redesigned the frontend delivery result as a vertical timeline (checkmark, date, location, then Express/COD/Prepaid rows connected by a line, ending in an order-cutoff box) — used consistently by the main widget, the "Check Now" popup, and the WooCommerce product-page checker.
* All timeline colors are still driven dynamically by the existing admin color settings (button/border colors) — no new hardcoded colors were introduced.
* No changes to AJAX behavior, delivery-date calculation, shortcodes, database, or settings — this release is frontend markup/CSS only.

= 1.4.0 =
* WordPress.org submission preparation: the plugin's folder, main file, and text domain changed from `pincode-delivery-estimator` to `servispin` to match the final public plugin identity. Internal identifiers that existing installs rely on — the database table, option names, AJAX actions, shortcodes (`[pincode_delivery_estimator]`, `[pincode_delivery_message]`), and CSS classes — are all unchanged, so existing pincode data and shortcode usage in your content continue working without edits.
* Updated `readme.txt` Contributors to the confirmed WordPress.org account (`officialwebfoo`).
* Added `== Privacy ==` and `== External Services ==` sections documenting the plugin's rate-limiting IP hashing, the optional uninstall-feedback email, local-storage usage, and the Google Fonts request — accurately reflecting the existing implementation, with no new data collection introduced.
* Clarified in the README that WooCommerce is optional — only the product-page compact checker requires it; every other feature works on any WordPress site.

= 1.3.2 =
* Hardened the uninstall-feedback popup's delete-link detection with a third, independent fallback (matching WordPress core's `id="delete-{slug}"` pattern), in case a site's markup doesn't match the first two detection strategies.

= 1.3.1 =
* Shortened the readme.txt short description to 146 characters (from ~196) for WordPress.org's directory/search display convention. The full description remains in the Description section.
* No functional code changes in this release — documentation/metadata only.

= 1.3.0 =
* Rebranded the plugin as ServisPin (Plugin Name, Author, Author URI, and description updated). The plugin slug, text domain, database table, and shortcode names are unchanged, so existing installs keep working without reconfiguration.
* Added an optional, skippable uninstall feedback prompt on the Plugins screen. Submitting it emails the feedback via `wp_mail()`; skipping it — or any failure to send — never blocks or delays uninstalling, and the existing opt-in data-deletion behavior in `uninstall.php` is unchanged.
* Added a "Download Sample CSV Template" button on the Bulk Upload screen, generating a CSV with the exact columns the importer expects.
* Updated readme.txt with Features, expanded FAQ, and Screenshots sections for WordPress.org.

= 1.2.1 =
* Fixed: PHP 8+ "Undefined array key" warning in `PDE_Database::update()` on partial updates (e.g. activate/deactivate), which only ever send a `status` field.
* Hardened: CSV export now neutralizes values that start with `=`, `+`, `-`, or `@` to prevent spreadsheet formula injection when opened in Excel/Sheets. Normal values (city, state, pincode, delivery estimate) are unaffected.
* Hardened: CSV bulk-upload validation now also checks the file against WordPress' allowed-mimes list, in addition to the file extension.
* Added a lightweight, transient-based per-IP rate limit on the public pincode-lookup endpoint to reduce scripted abuse. No login required, no data stored beyond a short-lived hashed-IP counter, and the limit is generous enough not to affect normal shoppers.
* Removed an unnecessary `flush_rewrite_rules()` call on deactivation (the plugin registers no rewrite rules, post types, or taxonomies).
* i18n: translation function calls now use a literal text-domain string as required by WordPress.org translation tooling.
* Added License / License URI to the plugin header and readme, plus FAQ and Screenshots sections in readme.txt.

= 1.2.0 =
* `[pincode_delivery_message]` no longer renders blank before a search — it now shows a "Check your delivery date" prompt with a "Check Now" link.
* Added a popup modal for checking delivery — opened from the message shortcode's "Check Now" link and the top bar's "Change Pincode" button.
* New Settings fields to customize the prompt and link text.

= 1.1.1 =
* Fixed: after a page refresh, the checker widget only pre-filled the last searched pincode but didn't show its result — the customer had to search again. It now automatically re-checks and displays the result (with a freshly recalculated delivery date) on load.

= 1.1.0 =
* Added expected delivery date + "order before X to get it by Y" urgency messaging (configurable daily cutoff time).
* Added Same-Day / Express Delivery badge, settable per pincode (Add/Edit screen or CSV `express_available` column).
* Added COD / Prepaid availability badges in the result box.
* New `express_available` database column (auto-added on upgrade via dbDelta — no manual migration needed).
* CSV export now includes `express_available`.

= 1.0.1 =
* Fixed compact widget spacing/border on product pages.

= 1.0.0 =
* Initial release.

== Upgrade Notice ==

= 1.4.0 =
Plugin identity changed to ServisPin (new folder/file/text-domain: servispin). If you're moving from an install named "Pincode Delivery Estimator", install this as a new plugin and deactivate/remove the old one — WordPress treats them as separate plugins, though your existing pincode data, settings, and shortcodes carry over untouched since none of the internal identifiers changed.
