Add unsend campaign feature (#45)

* Add unsend email editor

Add email editor

Add more email editor

Add renderer partial

Add more marketing email features

* Add more campaign feature

* Add variables

* Getting there

* campaign is there mfs

* Add migration
This commit is contained in:
KM Koushik
2024-08-10 10:09:10 +10:00
committed by GitHub
parent 0c072579b9
commit 5ddc0a7bb9
92 changed files with 11766 additions and 338 deletions

View File

@@ -0,0 +1,65 @@
import { Button } from "@unsend/ui/src/button";
import { CheckIcon } from "lucide-react";
import { useState, useCallback, useMemo } from "react";
export type LinkEditorPanelProps = {
initialUrl?: string;
onSetLink: (url: string) => void;
};
export const useLinkEditorState = ({
initialUrl,
onSetLink,
}: LinkEditorPanelProps) => {
const [url, setUrl] = useState(initialUrl || "");
const onChange = useCallback((event: React.ChangeEvent<HTMLInputElement>) => {
setUrl(event.target.value);
}, []);
const handleSubmit = useCallback(
(e: React.FormEvent) => {
e.preventDefault();
onSetLink(url);
},
[url, onSetLink]
);
return {
url,
setUrl,
onChange,
handleSubmit,
};
};
export const LinkEditorPanel = ({
onSetLink,
initialUrl,
}: LinkEditorPanelProps) => {
const state = useLinkEditorState({
onSetLink,
initialUrl,
});
return (
<div className="">
<form
onSubmit={state.handleSubmit}
className="flex items-center gap-2 justify-between"
>
<label className="flex items-center gap-2 p-2 rounded-lg cursor-text">
<input
className="flex-1 bg-transparent outline-none min-w-[12rem] text-black text-sm"
placeholder="Enter valid url"
value={state.url}
onChange={state.onChange}
/>
</label>
<Button variant="silent" size="sm" className="px-1">
<CheckIcon className="h-4 w-4 disabled:opacity-50" />
</Button>
</form>
</div>
);
};

View File

@@ -0,0 +1,33 @@
import { Button } from "@unsend/ui/src/button";
import { Edit2Icon, EditIcon, Trash2Icon } from "lucide-react";
export type LinkPreviewPanelProps = {
url: string;
onEdit: () => void;
onClear: () => void;
};
export const LinkPreviewPanel = ({
onClear,
onEdit,
url,
}: LinkPreviewPanelProps) => {
return (
<div className="flex items-center gap-2 p-2">
<a
href={url}
target="_blank"
rel="noopener noreferrer"
className="text-sm underline w-[12rem] overflow-hidden text-ellipsis"
>
{url}
</a>
<Button onClick={onEdit} variant="silent" size="sm" className="p-1">
<Edit2Icon className="h-4 w-4" />
</Button>
<Button onClick={onClear} variant="silent" size="sm" className="p-1">
<Trash2Icon className="h-4 w-4 text-destructive" />
</Button>
</div>
);
};