Skip to content

Commit

Permalink
merge: Merge pull request #86 from ArunaStorage/fix/mailing-list-regi…
Browse files Browse the repository at this point in the history
…stration

Fix mailing list registration component
  • Loading branch information
das-Abroxas authored Jun 26, 2024
2 parents 5bd8556 + d6894e1 commit 607d289
Show file tree
Hide file tree
Showing 4 changed files with 148 additions and 23 deletions.
113 changes: 91 additions & 22 deletions components/section/newsletter.vue
Original file line number Diff line number Diff line change
@@ -1,40 +1,109 @@
<script setup lang="ts">
import {EMAIL_REGEX} from "~/composables/constants";
import {IconCircleCheck, IconExclamationCircle} from "@tabler/icons-vue";
const email = ref('')
const emailInputInfo: Ref<string | undefined> = ref(undefined)
const displayName = ref('')
const processing = ref(false)
const success = ref(false)
async function submit() {
if (email.value.length <= 0) {
emailInputInfo.value = undefined
} else if (!EMAIL_REGEX.test(email.value)) {
emailInputInfo.value = 'Please enter a valid email address'
} else {
// Valid input
emailInputInfo.value = undefined
processing.value = true
// Try to register email to mailing list
await $fetch<boolean>('/api/newsletter_register', {
method: 'POST',
body: {
email: email.value,
}
}).then(result => {
console.log(result)
success.value = result
if (result) {
emailInputInfo.value = 'Subscribe request successfully sent.<br/>Please check your inbox for further instructions.'
} else {
emailInputInfo.value = 'Failed to send registration request.<br/>Please try again later or contact the website administrator.'
}
}).catch(err => {
console.log(err)
success.value = false
emailInputInfo.value = 'Failed to send registration request.<br/>Please try again later or contact the website administrator.'
}).finally(() => {
processing.value = false
})
}
}
</script>
<template>
<div
class="max-w-[85rem] w-full border-2 border-gray-300 shadow-lg rounded-3xl px-4 py-10 sm:px-6 lg:px-8 lg:py-16 mx-auto"
>
<div class="container w-full my-6 border-2 border-gray-400 rounded-md px-4 py-10 sm:px-6 lg:px-8 lg:py-16 mx-auto">
<div class="grid md:grid-cols-2 gap-8">
<div class="max-w-md">
<h2
class="text-2xl font-bold md:text-3xl md:leading-tight dark:text-white"
>
Subscribe
<h2 class="text-2xl font-bold md:text-3xl md:leading-tight dark:text-white">
Mailing List
</h2>
<p class="mt-3 text-gray-600 dark:text-gray-400">
Subscribe and start making the most of every engagement.
Subscribe and get all the latest Aruna updates and news.
</p>
</div>

<form>
<div class="w-full sm:max-w-lg md:ms-auto">
<div class="flex flex-col items-center gap-2 sm:flex-row sm:gap-3">
<div class="flex flex-col sm:flex-row items-top gap-2 sm:gap-3">
<div class="w-full">
<input
type="text"
id="hero-input"
name="hero-input"
class="py-3 px-4 block w-full border-gray-200 rounded-lg text-sm focus:border-aruna-600 focus:ring-blue-500 disabled:opacity-50 disabled:pointer-events-none dark:bg-slate-900 dark:border-gray-700 dark:text-gray-400 dark:focus:ring-gray-600"
placeholder="Enter your email"
/>
<!-- User Email Address -->
<div class="">
<div class="relative">
<input type="text"
id="user-mail-input"
v-model="email"
placeholder="Your email address"
class="peer p-4 block w-full border-gray-200 rounded-md text-sm placeholder:text-transparent focus:border-blue-500 focus:ring-blue-500 disabled:opacity-50 disabled:pointer-events-none dark:bg-slate-900 dark:border-gray-700 dark:text-gray-400 dark:focus:ring-gray-600
focus:pt-6
focus:pb-2
[&:not(:placeholder-shown)]:pt-6
[&:not(:placeholder-shown)]:pb-2
autofill:pt-6
autofill:pb-2">
<label class="text-slate-400 absolute top-0 start-0 p-4 h-full text-sm truncate pointer-events-none transition ease-in-out duration-100 border border-transparent dark:text-white peer-disabled:opacity-50 peer-disabled:pointer-events-none
peer-focus:text-xs
peer-focus:-translate-y-1.5
peer-focus:text-gray-500
peer-[:not(:placeholder-shown)]:text-xs
peer-[:not(:placeholder-shown)]:-translate-y-1.5
peer-[:not(:placeholder-shown)]:text-gray-500" for="user-mail-input">Your email address</label>
<div :class="{ 'hidden': emailInputInfo === undefined }"
class="absolute inset-y-0 end-0 flex items-center pointer-events-none pe-3">
<IconCircleCheck v-if="success" class="flex-shrink-0 size-4 text-green-500"/>
<IconExclamationCircle v-else class="flex-shrink-0 size-4 text-red-500"/>
</div>
</div>
<p id="user-mail-input-helper"
class="mt-2 text-sm text-center"
:class="{'hidden': emailInputInfo === undefined, 'text-red-600': !success, 'text-green-700': success}"
v-html="emailInputInfo"/>
</div>
<!-- End User Email Address -->
</div>
<a
class="w-full sm:w-auto whitespace-nowrap py-3 px-4 inline-flex justify-center items-center gap-x-2 text-sm font-semibold rounded-lg border border-transparent bg-aruna-700 text-white hover:bg-aruna-500 disabled:opacity-50 disabled:pointer-events-none dark:focus:outline-none dark:focus:ring-1 dark:focus:ring-gray-600"
href="#"
>
<button type="button"
@click="submit"
:disabled="processing"
class="w-full sm:w-auto whitespace-nowrap p-4 h-14 gap-x-2 text-sm font-semibold rounded-md border border-transparent bg-aruna-800 text-white hover:bg-aruna-700 disabled:opacity-50 disabled:pointer-events-none dark:focus:outline-none dark:focus:ring-1 dark:focus:ring-gray-600">
Subscribe
</a>
</button>

</div>
<p class="mt-3 text-sm text-gray-500">
No spam, unsubscribe at any time
No spam, unsubscribe at any time.
</p>
</div>
</form>
Expand Down
5 changes: 4 additions & 1 deletion nuxt.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,11 @@ export default defineNuxtConfig({
},

runtimeConfig: {
logRequests: true,
serverHostUrl: "http://localhost:8080",
logRequests: true,
mailingListHost: 'https://mailing-lists.example.de',
mailingListUrl: 'https://mailing-lists.example.de/lists/aruna/',
mailingListSubscribe: 'https://mailing-lists.example.de/lists/aruna/anonymous_subscribe',
provider: {
local: {
clientId: "test",
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
"@tabler/icons-vue": "^2.47.0",
"@tailwindcss/forms": "^0.5.7",
"autoprefixer": "^10.4.19",
"dom-parser": "^1.1.5",
"nuxt": "^3.12.2",
"postcss": "^8.4.38",
"preline": "^2.3.0",
Expand Down
52 changes: 52 additions & 0 deletions server/api/newsletter_register.post.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import {parseFromString} from 'dom-parser';

export default defineEventHandler(async event => {
// Fetch runtime config for mailing list connection properties
const config = useRuntimeConfig()

// Parse provided data for mailing list registry
const data = await readBody(event)

// Validate provided data is present
if (!data.email) {
throw new Error('Email is not defined')
}

// Fetch CSRF tokens
const csrfToken: string = await $fetch<string>(config.mailingListUrl)
.then((responseText) => {
const dom = parseFromString(responseText)
const elements = dom.getElementsByName('csrfmiddlewaretoken')

if (elements.length < 1) {
console.error('[Newsletter Register] No token available on mailing list page')
throw new Error("Page did not contain token")
}

const token = elements[0].getAttribute('value')
console.log(token)

return token
})

// Prepare form data for registration request
let formData = new FormData();
formData.append('email', data.email as string);
formData.append('display_name', data.displayName ? data.displayName : '');
formData.append('csrfmiddlewaretoken', csrfToken);

// Send registration to mailing list endpoint
return await $fetch(config.mailingListSubscribe, {
method: 'POST',
headers: {
Referer: config.mailingListUrl,
Origin: config.mailingListHost,
Cookie: `csrftoken=${csrfToken}`,
},
body: formData
}).then(response => {
return true
}).catch(err => {
return false
})
})

0 comments on commit 607d289

Please sign in to comment.