Skip to content

Test fix for sms csv download link #281

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion authentication/sms.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,18 @@ description: "SMS authentication enables users to authenticate their Turnkey acc
sidebarTitle: "SMS"
---

import { priceDataJson } from "/snippets/smsPriceData.mdx";

import { SmsPriceLookup } from "/snippets/SmsPriceLookup.mdx";

## Access and Pricing

SMS authentication is available to all Enterprise customers. To enable this feature, please reach out to the Turnkey team.

SMS pricing is usage-based and varies depending on the country of the destination phone number. A downloadable price list for all supported countries is available <a href="/assets/files/sms-prices.csv" download>here as a CSV</a>.
SMS pricing is usage-based and varies depending on the country of the destination phone number.
Select your country below to view pricing.

<SmsPriceLookup priceDataJson={priceDataJson} />

## How It Works

Expand Down
60 changes: 60 additions & 0 deletions download.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
// Wait for the DOM to be fully loaded before running the script
document.addEventListener('DOMContentLoaded', () => {
// Find the specific download link by its ID
const smsDownloadLink = document.getElementById('sms-price-download-link');

if (smsDownloadLink) {
smsDownloadLink.addEventListener('click', async (event) => {
event.preventDefault(); // Stop the browser from following the link directly

const linkElement = event.currentTarget; // Get the link element itself
const fileUrl = linkElement.getAttribute('href');
const downloadFileName = linkElement.getAttribute('download') || 'download';

// Add a visual indicator (optional)
const originalText = linkElement.textContent;
linkElement.textContent = 'Downloading...';
linkElement.style.pointerEvents = 'none'; // Disable further clicks while processing

try {
console.log(`Fetching ${fileUrl} for download...`);
const response = await fetch(fileUrl);

if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status} for ${response.url}`);
}

const blob = await response.blob();
const url = window.URL.createObjectURL(blob);
const tempLink = document.createElement('a');
tempLink.href = url;
tempLink.setAttribute('download', downloadFileName);

document.body.appendChild(tempLink);
tempLink.click();
document.body.removeChild(tempLink);

window.URL.revokeObjectURL(url);
console.log('Download triggered successfully.');

} catch (error) {
console.error('Download failed:', error);
// Provide feedback to the user (optional)
linkElement.textContent = 'Download Failed!';
// Consider adding a title attribute with the error for more details
linkElement.setAttribute('title', `Error: ${error.message}`);
// Don't restore original text on failure, so user knows it failed
return; // Exit early

} finally {
// Restore link text and clickability only on success or if no error occurred
if (linkElement.textContent !== 'Download Failed!') {
linkElement.textContent = originalText;
}
linkElement.style.pointerEvents = 'auto';
}
});
} else {
console.log('SMS price download link not found on this page.');
}
});
83 changes: 83 additions & 0 deletions snippets/SmsPriceLookup.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
export const SmsPriceLookup = ({ priceDataJson }) => {

const countries = Object.keys(priceDataJson).sort();

const toggleVisibility = () => {
const targetDiv = document.getElementById('hidden-content-simple');
if (targetDiv) {
const isOpen = targetDiv.getAttribute('data-open') === 'true';
targetDiv.setAttribute('data-open', !isOpen);
}
}

const selectCountry = (country) => {
const selectElement = document.getElementById('sms-country-select-simple');
const buttonElement = document.getElementById('country-toggle-button');
const targetDiv = document.getElementById('hidden-content-simple');
const priceDisplayElement = document.getElementById('sms-price-display');

if (selectElement) {
selectElement.value = country;
}
if (buttonElement) {
buttonElement.textContent = country;
}
if (priceDisplayElement && priceDataJson[country]) {

const price = priceDataJson[country];

priceDisplayElement.textContent = `${price}¢`;
}
if (targetDiv) {
targetDiv.setAttribute('data-open', 'false');
}
}

return (

<div className="relative">
<div className="text-lg font-medium text-black/70 dark:text-white mb-8">
Select Your Country To View Pricing
</div>
<div className="flex gap-12 items-center items-center rounded-lg callout px-5 py-4 overflow-hidden rounded-2xl flex gap-3 border border-zinc-500/20 bg-zinc-50/50 dark:border-zinc-500/30 dark:bg-zinc-500/10">
<button
id="country-toggle-button"
onClick={toggleVisibility}
className="card w-full block not-prose font-normal group relative py-3 px-3 ring-2 ring-transparent rounded-xl bg-white dark:bg-background-dark border border-gray-950/10 dark:border-white/10 overflow-hidden cursor-pointer hover:!border-primary dark:hover:!border-primary-light"
>
Select Country
</button>
<div className="w-full flex flex-col gap-1 items-center">
<div className="text-sm font-medium text-black/70 dark:text-white">Cost</div>
<div id="sms-price-display" className="font-medium text-black/70 dark:text-white text-xl">0.000¢</div>

</div>

<div
id="hidden-content-simple"
data-open="false"
style={{
top: "calc(100% + 0px)",
}}
className="text-base bg-background-light dark:bg-background-dark absolute z-50 max-h-96 max-w-[var(--radix-dropdown-menu-content-available-width)] min-w-[var(--radix-dropdown-menu-trigger-width)] overflow-y-auto rounded-xl border-standard text-gray-950/70 dark:text-white/70 p-1 gap-2"
>
<div>
{countries.map((country) => (
<div
key={country}
style={{ padding: "0.5rem", cursor: "pointer" }}
className="hover:bg-gray-100 rounded-md hover:dark:bg-gray-800"
onClick={() => selectCountry(country)}
>
{country}
</div>
))}
</div>
</div>

</div>

</div>

);
};
139 changes: 139 additions & 0 deletions snippets/smsPriceData.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
export const priceDataJson = {
"Albania": 9.029,
"Andorra": 11.380,
"Angola": 8.983,
"Argentina": 6.928,
"Armenia": 14.113,
"Australia": 3.450,
"Austria": 10.526,
"Azerbaijan": 36.910,
"Bahamas": 7.011,
"Bahrain": 3.549,
"Bangladesh": 24.928,
"Barbados": 13.238,
"Belgium": 9.582,
"Belize": 26.502,
"Benin": 12.250,
"Bolivia": 14.057,
"Bosnia And Herzegovina": 7.463,
"Botswana": 3.831,
"Brazil": 2.297,
"British Virgin Islands": 18.022,
"Brunei": 1.289,
"Cameroon": 12.333,
"Cape Verde": 13.740,
"Cayman Islands": 7.300,
"Chad": 14.440,
"Chile": 5.178,
"Colombia": 0.157,
"Costa Rica": 4.678,
"Croatia": 8.741,
"Curacao": 12.667,
"Cyprus": 2.995,
"Czechia": 6.609,
"Democratic Republic Of The Congo": 11.435,
"Denmark": 6.206,
"Djibouti": 11.180,
"Dominica": 13.002,
"Ecuador": 17.655,
"El Salvador": 6.609,
"Equatorial Guinea": 13.060,
"Estonia": 7.687,
"Faroe Islands": 4.369,
"Fiji": 15.002,
"Finland": 10.009,
"France": 6.933,
"French Polynesia": 12.860,
"Gambia": 8.444,
"Georgia": 17.028,
"Germany": 8.848,
"Ghana": 16.611,
"Gibraltar": 7.611,
"Greece": 8.621,
"Grenada": 14.593,
"Guadelupe": 16.302,
"Guatemala": 10.060,
"Guinea": 14.260,
"Guyana": 11.133,
"Haiti": 16.299,
"Honduras": 8.310,
"Hong Kong": 7.656,
"Hungary": 10.824,
"Iceland": 9.640,
"India": 6.900,
"Indonesia": 36.308,
"Ireland": 9.556,
"Israel": 17.031,
"Italy": 7.500,
"Ivory Coast": 19.076,
"Jamaica": 16.714,
"Japan": 7.451,
"Kosovo": 11.404,
"Kuwait": 14.940,
"Kyrgyzstan": 20.282,
"Laos": 5.365,
"Latvia": 6.848,
"Lebanon": 25.954,
"Lesotho": 9.890,
"Liberia": 8.793,
"Lithuania": 4.358,
"Luxembourg": 8.412,
"Madagascar": 36.064,
"Malaysia": 15.107,
"Maldives": 4.149,
"Mali": 27.733,
"Malta": 6.980,
"Mauritius": 15.744,
"Mexico": 5.956,
"Moldova": 6.226,
"Mongolia": 12.765,
"Montenegro": 6.569,
"Morocco": 17.586,
"Mozambique": 12.638,
"Namibia": 8.284,
"Nepal": 15.017,
"Netherlands": 11.890,
"New Zealand": 9.416,
"Nicaragua": 7.773,
"Niger": 26.123,
"Nigeria": 22.809,
"Norway": 8.675,
"Pakistan": 33.692,
"Panama": 8.786,
"Peru": 9.209,
"Philippines": 15.885,
"Poland": 3.222,
"Portugal": 3.031,
"Puerto Rico 1": 1.356,
"Puerto Rico 2": 1.356,
"Qatar": 3.973,
"Reunion": 17.186,
"Romania": 7.804,
"Saint Lucia": 8.100,
"Saint Vincent And Grenadines": 13.192,
"Samoa": 15.394,
"Saudi Arabia": 10.154,
"Senegal": 18.815,
"Serbia": 5.100,
"Seychelles": 4.272,
"Sierra Leone": 18.370,
"Singapore": 3.918,
"Slovenia": 14.522,
"South Africa": 1.980,
"South Korea": 2.414,
"Spain": 6.087,
"Suriname": 12.681,
"Swaziland": 8.031,
"Sweden": 7.256,
"Switzerland": 5.124,
"Tajikistan": 44.377,
"Tanzania": 19.222,
"Thailand": 1.272,
"Togo": 14.970,
"Trinidad And Tobago": 12.953,
"Tunisia": 25.684,
"United States": 0.581,
"Uruguay": 7.317,
"Uzbekistan": 36.803,
"Venezuela": 6.780
};
82 changes: 82 additions & 0 deletions styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,85 @@
Link: /home#feature-spotlight%3A-send-crypto-via-a-url */
display: none;
}

/* Custom Dropdown for SMS Price Lookup */
.sms-price-lookup-container {
/* Container needs relative positioning for absolute list */
position: relative;
margin-top: 1rem;
margin-bottom: 1rem;
}

.sms-country-trigger {
/* Make button look like a select input */
display: block;
width: 100%;
padding: 0.5rem 0.75rem;
font-size: 1rem;
font-family: inherit; /* Use site's font */
line-height: 1.5;
color: #495057; /* Standard text color */
background-color: #fff;
background-clip: padding-box;
border: 1px solid #ced4da; /* Standard border */
border-radius: 0.25rem;
text-align: left;
cursor: pointer;
/* Add space for a dropdown arrow indicator */
padding-right: 2rem;
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23343a40' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M2 5l6 6 6-6'/%3e%3c/svg%3e");
background-repeat: no-repeat;
background-position: right 0.75rem center;
background-size: 16px 12px;
}

.sms-country-list {
/* Style the dropdown list */
display: none; /* Hidden by default */
position: absolute;
top: 100%; /* Position below trigger */
left: 0;
width: 100%;
max-height: 200px; /* Fixed height with scroll */
overflow-y: auto;
background-color: #fff;
border: 1px solid #ced4da;
border-top: none; /* Avoid double border with trigger */
border-radius: 0 0 0.25rem 0.25rem;
z-index: 1000; /* Ensure it's on top */
box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15);
margin: 0;
padding: 0;
list-style: none;
}

.sms-country-item {
/* Style individual country items */
display: block;
width: 100%;
padding: 0.5rem 0.75rem;
font-size: 1rem;
font-family: inherit;
color: #495057;
text-align: left;
background-color: transparent;
border: none;
cursor: pointer;
white-space: nowrap; /* Prevent wrapping */
}

.sms-country-item:hover,
.sms-country-item:focus {
background-color: #f8f9fa; /* Subtle hover effect */
color: #16181b;
outline: none;
}

/* CSS to control visibility based on data-open attribute */
#hidden-content-simple[data-open="false"] {
display: none;
}

#hidden-content-simple[data-open="true"] {
display: block; /* Or inline, inline-block, etc., as needed */
}