Files
traxxx-web/components/emails/alert.vue

287 lines
8.5 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<script setup>
import {
Body,
Column,
Container,
Heading,
Html,
Img,
Link,
Preview,
Row,
Text,
} from '@vue-email/components';
import { format } from 'date-fns';
defineProps({
triggers: {
type: Array,
default: () => mockTriggers,
},
user: {
type: Object,
default: () => mockUser,
},
address: {
type: String,
default: 'http://localhost:5100',
},
});
</script>
<script>
// defineProps' default factory (above, in <script setup>) references this. It must live in a plain
// <script> block: Vue's compiler forbids defineProps from referencing variables declared inside
// <script setup> itself, since that block gets hoisted out of the setup() function.
const mockUser = {
id: 1,
username: 'DebuggingLibrarian',
email: 'debug@alerts.traxxx.me',
};
const mockTriggers = [
{
scene: {
id: 684061,
title: 'Thick & Bootylicious: Vanessa Blake Takes A BBC Up Her Ass',
slug: 'thick-bootylicious-vanessa-blake-takes-a-bbc-up',
date: '2026-02-17T00:00:00.000Z',
description: 'Vanessa Blakes curves are impossible to ignore—especially her thick, round, bootylicious ass. The scene opens with the camera following Vanessa through the house as she struts confidently in a slow, teasing booty walk, giving viewers a full view of her luscious curves. She pauses at the stairs, turning back to flaunt her massive ass before letting her hands wander over her body. Feeling the heat build, Vanessa begins to pleasure herself, showcasing her insatiable appetite for big black cock. Moving to the couch, she grabs a dildo and slowly works it into her ass, preparing herself for whats coming next. Sitting back and watching the show is Lexington Steele, enjoying every second as she stretches and teases in anticipation. Lexington finally steps in, and Vanessa eagerly drops to her knees, wrapping her lips around his massive BBC and giving him a deep, hungry blowjob. The action quickly escalates to the couch, where they fuck in multiple intense positions, Vanessas thick body bouncing with every thrust. When shes fully ready, Vanessa has Lex slide his BBC deep into her ass, and the two go at it hard in a variety of explosive anal positions. The scene builds to a powerful climax as Lexington pulls out and finishes with a messy facial, leaving Vanessa satisfied and dripping after an unforgettable session.',
actors: [
{
id: 919,
name: 'Vanessa Blake',
},
{
id: 1374,
name: 'Lexington Steele',
},
],
actorIds: [
919,
1374,
],
tags: [
{
name: 'MILF',
slug: 'milf',
},
{
name: 'facial',
slug: 'facial',
},
],
tagIds: [
4,
12,
19,
30,
29,
37,
41,
68,
82,
100,
112,
119,
null,
130,
],
entityId: 522,
parentEntityId: 47,
},
posterUrl: 'http://localhost:5100/media/posters/lazy/cd/b5/99375c7998a20acffef2217a8a21c3546924312cec65.jpeg',
alertId: 123,
alertActors: [],
alertTags: [],
alertEntities: [
{
id: 522,
name: 'Jules Jordan',
},
],
alertMatches: [],
alertSceneIds: [],
},
{
scene: {
id: 684060,
title: 'Elizabeth Skylars Big ASSets Drive The Milfomaniac Manuel Ferrara Wild',
slug: 'elizabeth-skylar-s-big-assets-drive-the-manuel',
date: '2026-02-21T00:00:00.000Z',
description: 'Elizabeth Skylar is ready to indulge her cravings, and theres only one man she wants—the Milfomaniac, Manuel Ferrara. The scene opens with Elizabeth stepping out onto the balcony in sexy lingerie, confidently showing off her busty curves as the camera captures every seductive angle. She teases the viewer with slow, deliberate poses before heading inside to the kitchen, where she perches on a stool with her ass on full display. Manuel joins her, grabbing and admiring her curves, letting the camera in on just how irresistible she is. The action moves to the living room, where Elizabeth stretches out on the couch and begins to pleasure herself, putting on a sultry show for Manuel. Unable to resist, she drops to her knees, her tits spilling free as she takes him deep into her mouth with an eager, hungry intensity. From there, the two tear into each other on the couch, fucking in multiple positions as Elizabeth moans for more. The scene builds to a explosive finish, ending with Manuel delivering a memorable facial that leaves Elizabeth completely satisfied.',
actors: [
{
id: 44001,
name: 'Elizabeth Skylar',
},
{
id: 512,
name: 'Manuel Ferrara',
},
],
actorIds: [
512,
44001,
],
tags: [
{
name: 'anal',
slug: 'anal',
},
{
name: 'ass to mouth',
tag: 'atm',
},
],
tagIds: [
4,
30,
29,
31,
37,
41,
68,
82,
119,
125,
],
entityId: 522,
parentEntityId: 47,
},
posterUrl: 'http://localhost:5100/media/posters/lazy/3c/84/f53e772e4710ca71fb74bdb6896af3d180725d17710b.jpeg',
alertId: 123,
alertActors: [],
alertTags: [],
alertEntities: [
{
id: 522,
name: 'Jules Jordan',
},
],
alertMatches: [],
alertSceneIds: [],
},
];
</script>
<template>
<Html>
<Body style="font-family: sans-serif;">
<Preview>{{ triggers.length }} new scene{{ triggers.length === 1 ? '' : 's' }} matching your alerts on traxxx</Preview>
<Container>
<Img
:src="`${address}/img/logo.png`"
width="150"
alt="traxxx"
style="margin: 15px auto 25px auto;"
/>
<Heading
as="h3"
style="color: #f65596; margin: 0 auto 0 auto;"
>Hi, {{ user.username }}</Heading>
<Text style="font-size: 16px; margin: 20px 0;">Scenes for which you set e-mail alerts have been added or released:</Text>
<div
v-for="(trigger, index) in triggers"
:key="trigger.scene.id"
style="margin-bottom: 15px; font-size: 14px;"
:style="{
'padding-bottom': index < triggers.length - 1 ? '15px' : 0,
'border-bottom': index < triggers.length - 1 ? 'solid 1px #ddd' : 'none',
}"
>
<Row style="margin-bottom: 8px;">
<Column valign="top">
{{ format(trigger.scene.date, 'yyyy-MM-dd') }} |
<span v-if="trigger.alertSceneIds.length > 0">Scene is released</span>
<span v-else>
New
<template
v-if="trigger.alertTags.length > 0"
>{{ trigger.alertTags.map((tag) => tag.name).join(', ') }}</template>
scene
<template
v-if="trigger.alertActors.length > 0"
>with {{ trigger.alertActors.map((actor) => actor.name).join(', ') }}&nbsp;</template>
<template
v-if="trigger.alertEntities.length > 0"
>for {{ trigger.alertEntities[0].name }}&nbsp;</template>
<template
v-if="trigger.alertMatches.length > 0"
>matching {{ trigger.alertMatches.map((match) => match.expression).join(', ') }}</template>
</span>
</Column>
<Column
width="50"
valign="top"
style="text-align: right;"
>
<span style="font-size: 14px; color: #aaa;">#{{ trigger.alertId }}</span>
</Column>
</Row>
<div>
<Row>
<Column
width="175"
valign="top"
>
<Link :href="`${address}/scene/${trigger.scene.id}/${trigger.scene.slug}`">
<Img
v-if="trigger.posterUrl"
:src="trigger.posterUrl"
width="160"
:alt="trigger.scene.title"
style="margin-top: 2px; border-radius: 8px;"
/>
<div
v-else
style="width: 144px; height: 74px; background: #eee; color: #aaa; text-align: center; border-radius: 8px; padding: 8px;"
>No thumb</div>
</Link>
</Column>
<Column valign="top">
<div style="margin-bottom: 5px;">
<Link
:href="`${address}/scene/${trigger.scene.id}/${trigger.scene.slug}`"
style="font-weight: bold; line-height: 1.5; color: inherit;"
>{{ trigger.scene.title }}</Link>
</div>
<div style="margin-bottom: 8px;">
<span style="font-size: 14px;">{{ trigger.scene.actors.slice(0, 3).map((actor) => actor.name).join(', ') }}</span>
</div>
<div style="margin-bottom: 8px;">
<span style="font-size: 14px; color: #666;">{{ trigger.scene.tags.slice(0, 5).map((tag) => tag.name).join(', ') }}</span>
</div>
</Column>
</Row>
</div>
</div>
<Heading
as="h3"
style="margin-top: 30px;"
>Enjoy!</Heading>
<span style="font-size: 14px; color: #aaa;">Delivered by the Automated Notification and Alert Link</span>
</Container>
</Body>
</Html>
</template>