Skip to content

Instantly share code, notes, and snippets.

@drawveloper
Created December 2, 2024 22:23
Show Gist options
  • Save drawveloper/dacf5f3939339efef9872edd999612fa to your computer and use it in GitHub Desktop.
Save drawveloper/dacf5f3939339efef9872edd999612fa to your computer and use it in GitHub Desktop.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Startup Offer Generator</title>
<script src="https://cdn.tailwindcss.com"></script>
<script type="module">
import { getSDK } from "https://webdraw.ai/webdraw-sdk";
const sdk = await getSDK();
const form = document.getElementById('offerForm');
const input = document.getElementById('offerInput');
const table = document.getElementById('compensationTable');
const submitBtn = document.getElementById('submitBtn');
const spinner = document.getElementById('spinner');
const errorMsg = document.getElementById('errorMsg');
form.addEventListener('submit', async (e) => {
e.preventDefault();
const userInput = input.value.trim();
if (!userInput) {
showError('Please enter a description of the offer.');
return;
}
// Show loading state
submitBtn.disabled = true;
spinner.classList.remove('hidden');
table.classList.add('opacity-50');
hideError();
try {
const response = await sdk.ai.message({
messages: [{ role: 'user', content: userInput }],
system: `You are a compensation calculator assistant. For the input text, analyze and project company growth with these requirements:
- Project valuations for up to 5 years
- Target reaching $1B valuation within 5 years if reasonable based on input
- Return a JSON object with this exact structure:
{
"company_data": {
"initial_shares": 10000000,
"rounds": [{
"year": number,
"valuation": number,
"dilution_percentage": number
}]
},
"compensation_package": {
"base_salary": number,
"stock_options": {
"shares": number
}
}
}`,
});
let data;
try {
const content = response.content[0].text;
// Find the JSON object in the response
const jsonMatch = content.match(/\{[\s\S]*\}/);
if (!jsonMatch) {
throw new Error('No valid JSON found in response');
}
data = JSON.parse(jsonMatch[0]);
updateTable(data);
} catch (e) {
showError('Unable to process the AI response. Please try rephrasing your input.');
console.error('Parse error:', e);
}
} catch (error) {
showError('Failed to generate offer. Please try again.');
console.error('API error:', error);
}
// Hide loading state
submitBtn.disabled = false;
spinner.classList.add('hidden');
table.classList.remove('opacity-50');
});
function showError(message) {
errorMsg.textContent = message;
errorMsg.classList.remove('hidden');
}
function hideError() {
errorMsg.classList.add('hidden');
}
function updateTable(data) {
let currentTotalShares = data.company_data.initial_shares;
const years = data.company_data.rounds.map(round => {
const stockOptions = data.compensation_package.stock_options.shares;
currentTotalShares = currentTotalShares * (1 + round.dilution_percentage / 100);
const equityPercentage = (stockOptions / currentTotalShares) * 100;
const equityValue = (equityPercentage / 100) * round.valuation;
return {
year: round.year,
companyValuation: round.valuation,
dilutionPercentage: round.dilution_percentage,
totalShares: Math.round(currentTotalShares),
stockOptions: stockOptions,
equityPercentage: equityPercentage,
equityValue: equityValue,
salary: data.compensation_package.base_salary,
totalCompensation: data.compensation_package.base_salary + equityValue
};
});
const tbody = document.querySelector('#compensationTable tbody');
tbody.innerHTML = '';
years.forEach(year => {
const row = document.createElement('tr');
row.innerHTML = `
<td class="border px-4 py-2">${year.year}</td>
<td class="border px-4 py-2">$${year.companyValuation.toLocaleString()}</td>
<td class="border px-4 py-2">${year.dilutionPercentage}%</td>
<td class="border px-4 py-2">${Math.round(year.totalShares).toLocaleString()}</td>
<td class="border px-4 py-2">${year.stockOptions.toLocaleString()}</td>
<td class="border px-4 py-2">${year.equityPercentage.toFixed(4)}%</td>
<td class="border px-4 py-2">$${Math.round(year.equityValue).toLocaleString()}</td>
<td class="border px-4 py-2">$${year.salary.toLocaleString()}</td>
<td class="border px-4 py-2">$${Math.round(year.totalCompensation).toLocaleString()}</td>
`;
tbody.appendChild(row);
});
}
</script>
</head>
<body class="bg-gray-100 min-h-screen p-8">
<div class="max-w-7xl mx-auto bg-white rounded-lg shadow-lg p-6">
<h1 class="text-3xl font-bold mb-8 text-center">Startup Offer Generator</h1>
<!-- Input Form -->
<div class="max-w-2xl mx-auto mb-8">
<form id="offerForm" class="space-y-4">
<textarea
id="offerInput"
class="w-full h-32 p-4 border rounded"
placeholder="Describe the valuation story, expected valuations, salary, stock options, and total company shares. The AI will project growth for up to 5 years targeting $1B valuation if feasible."
></textarea>
<div id="errorMsg" class="hidden text-red-500 text-center mb-4"></div>
<div class="flex justify-center">
<button
id="submitBtn"
type="submit"
class="bg-blue-500 text-white px-6 py-2 rounded hover:bg-blue-600 flex items-center space-x-2"
>
<span>Generate Offer</span>
<div id="spinner" class="hidden animate-spin rounded-full h-4 w-4 border-b-2 border-white"></div>
</button>
</div>
</form>
</div>
<!-- Compensation Table -->
<div class="overflow-x-auto">
<table id="compensationTable" class="w-full table-auto">
<thead>
<tr class="bg-gray-100">
<th class="border px-4 py-2">Year</th>
<th class="border px-4 py-2">Company Valuation</th>
<th class="border px-4 py-2">Dilution %</th>
<th class="border px-4 py-2">Total Shares</th>
<th class="border px-4 py-2">Stock Options</th>
<th class="border px-4 py-2">Equity %</th>
<th class="border px-4 py-2">Equity Value</th>
<th class="border px-4 py-2">Salary</th>
<th class="border px-4 py-2">Total Compensation</th>
</tr>
</thead>
<tbody></tbody>
</table>
</div>
</div>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment