feat: initial implementation of WooList phpList Integration plugin v1.0.0

- phpList REST API wrapper with subscriber get-or-create + list assignment
- WooCommerce Settings tab (5 sections: connection, orders, signup, newsletter)
- Test Connection button via admin-post action
- Hooks for order completed/cancelled and user_register events
- [woolist_newsletter] shortcode with jQuery AJAX, fixed & auto-generated coupons
- Responsive front-end form styles and JS with loading/success/error states

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-19 11:51:12 +01:00
commit 6e23e40bf3
7 changed files with 1055 additions and 0 deletions

View File

@@ -0,0 +1,88 @@
/* ==========================================================================
WooList — Newsletter Form Styles
========================================================================== */
.woolist-newsletter-wrap {
max-width: 480px;
margin: 1.5em auto;
font-family: inherit;
}
/* Form row: input + button side by side */
.woolist-form-row {
display: flex;
gap: 0.5em;
flex-wrap: wrap;
}
.woolist-email-input {
flex: 1 1 auto;
min-width: 0;
padding: 0.65em 0.9em;
font-size: 1em;
border: 1px solid #ccc;
border-radius: 4px;
outline: none;
transition: border-color 0.2s ease;
box-sizing: border-box;
}
.woolist-email-input:focus {
border-color: #0071a1;
box-shadow: 0 0 0 2px rgba(0, 113, 161, 0.15);
}
.woolist-submit-btn {
flex: 0 0 auto;
padding: 0.65em 1.4em;
font-size: 1em;
font-weight: 600;
color: #fff;
background-color: #0071a1;
border: none;
border-radius: 4px;
cursor: pointer;
transition: background-color 0.2s ease, opacity 0.2s ease;
white-space: nowrap;
}
.woolist-submit-btn:hover {
background-color: #005f8a;
}
.woolist-submit-btn:disabled {
opacity: 0.6;
cursor: not-allowed;
}
/* Response message area */
.woolist-response {
margin-top: 0.85em;
padding: 0.75em 1em;
border-radius: 4px;
font-size: 0.95em;
line-height: 1.5;
}
.woolist-response.woolist-success {
background-color: #edfaf1;
border: 1px solid #52c41a;
color: #2d6a0f;
}
.woolist-response.woolist-error {
background-color: #fff1f0;
border: 1px solid #ff4d4f;
color: #a8071a;
}
/* Responsive: stack on very small screens */
@media (max-width: 360px) {
.woolist-form-row {
flex-direction: column;
}
.woolist-submit-btn {
width: 100%;
}
}

View File

@@ -0,0 +1,69 @@
/* global woolist, jQuery */
( function ( $ ) {
'use strict';
$( document ).on( 'submit', '#woolist-newsletter-form', function ( e ) {
e.preventDefault();
var $form = $( this );
var $wrap = $form.closest( '.woolist-newsletter-wrap' );
var $btn = $form.find( '.woolist-submit-btn' );
var $email = $form.find( '[name="woolist_email"]' );
var $resp = $wrap.find( '.woolist-response' );
// Clear previous response state.
$resp.hide().removeClass( 'woolist-success woolist-error' ).html( '' );
var email = $email.val().trim();
if ( ! email ) {
showResponse( $resp, woolist.i18n.error, false );
return;
}
// Loading state.
var originalLabel = $btn.text();
$btn.prop( 'disabled', true ).text( woolist.i18n.subscribing );
$.ajax( {
url: woolist.ajaxurl,
method: 'POST',
data: {
action: 'woolist_newsletter_submit',
nonce: woolist.nonce,
woolist_email: email,
},
} )
.done( function ( response ) {
if ( response.success && response.data && response.data.message ) {
// Hide the form, show the success message.
$form.slideUp( 200 );
showResponse( $resp, response.data.message, true );
} else {
var msg = ( response.data && response.data.message )
? response.data.message
: woolist.i18n.error;
showResponse( $resp, msg, false );
$btn.prop( 'disabled', false ).text( originalLabel );
}
} )
.fail( function () {
showResponse( $resp, woolist.i18n.error, false );
$btn.prop( 'disabled', false ).text( originalLabel );
} );
} );
/**
* Display a response message in the response container.
*
* @param {jQuery} $el The response element.
* @param {string} message HTML or text message to display.
* @param {boolean} success Whether this is a success message.
*/
function showResponse( $el, message, success ) {
$el
.addClass( success ? 'woolist-success' : 'woolist-error' )
.html( message )
.slideDown( 200 );
}
} )( jQuery );