last working index
Flag: 📍 Modified: February 14, 2026 7:58 PM Created: October 16, 2025 5:48 PM Master Type: Notes Hide: No Starred: No Status: Unassigned
<?php
// CONFIG
$drupal_base = "https://hub.sea-meets-sky.com/main";
$jsonapi_notes = "$drupal_base/jsonapi/node/n";
$username = "admin";
$password = "And1mJavert!";
// Handle note submission
if (!empty($_POST['note_body'])) {
$title = trim(explode("\n", $_POST['note_body'])[0] ?: 'Untitled Note');
$body = $_POST['note_body'];
$inbox = !empty($_POST['field_inbox']);
$payload = [
'data' => [
'type' => 'node--n',
'attributes' => [
'title' => $title,
'body' => ['value' => $body, 'format' => 'plain_text'],
'field_inbox' => $inbox ? true : false,
]
]
];
$ch = curl_init($jsonapi_notes);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/vnd.api+json']);
curl_setopt($ch, CURLOPT_USERPWD, "$username:$password");
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_exec($ch);
curl_close($ch);
header("Location: " . $_SERVER['PHP_SELF']);
exit;
}
// Fetch notes helper
function fetch_notes($filter = '') {
global $jsonapi_notes, $username, $password;
$url = $jsonapi_notes . $filter . (str_contains($filter, '?') ? '&' : '?') . 'sort=-created';
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_USERPWD, "$username:$password");
$response = curl_exec($ch);
curl_close($ch);
$data = json_decode($response, true);
return $data['data'] ?? [];
}
// Preload columns
$inbox_notes = fetch_notes('?filter[field_inbox][value]=1');
$two_weeks_ago = date('c', strtotime('-2 weeks'));
$recent_notes = fetch_notes("?filter[created][value]=$two_weeks_ago&filter[created][operator]=>=");
$all_notes = fetch_notes('');
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Quick Capture Notes</title>
<style>
:root {
--bg-color:#f9f9f9;
--text-color:#222;
--column-bg:#fff;
--note-hover:#e6e6e6;
--button-bg:#007bff;
--button-text:#fff;
--save-inactive:#ccc;
--save-active:#28a745;
}
@media (prefers-color-scheme: dark) {
:root {
--bg-color:#121212;
--text-color:#e0e0e0;
--column-bg:#1e1e1e;
--note-hover:#333;
--button-bg:#1e88e5;
--button-text:#fff;
--save-inactive:#555;
--save-active:#43a047;
}
}
body { font-family:sans-serif; margin:20px; background:var(--bg-color); color:var(--text-color);}
button { cursor:pointer; background:var(--button-bg); color:var(--button-text); border:none; border-radius:4px; padding:6px 12px;}
.columns { display:flex; gap:20px; margin-top:20px; flex-wrap:wrap;}
.column { flex:1; min-width:250px; background:var(--column-bg); padding:10px; border:1px solid #ccc; border-radius:4px;}
.note-item { cursor:pointer; padding:8px 10px; margin:4px 0; border-bottom:1px solid #ddd;}
.note-item:hover { background:var(--note-hover);}
#quick-capture-btn { padding:10px 20px; font-size:1.1em;}
/* Popover container */
#quick-capture-popover {
display:none;
position:absolute;
width:350px;
max-width:90%;
background:var(--column-bg);
border:1px solid #ccc;
padding:15px;
box-shadow:0 2px 6px rgba(0,0,0,0.2);
z-index:1000;
border-radius:4px;
transition: all 0.2s ease;
}
/* Textarea (identical on desktop and mobile) */
#quick-capture-popover textarea {
width:100%;
flex:1;
font-size:1em;
padding:12px;
border:1px solid #ccc;
border-radius:4px;
background:var(--column-bg);
color:var(--text-color);
resize:vertical;
box-sizing:border-box;
outline:none;
}
/* Save button */
#save-button {
position:absolute;
bottom:10px;
right:10px;
padding:8px 16px;
border-radius:4px;
background:var(--save-inactive);
opacity:0.6;
cursor:not-allowed;
border:none;
}
#save-button.active { background:var(--save-active); opacity:1; cursor:pointer; }
/* Inbox toggle */
#inbox-toggle {
display:inline-block;
font-family:monospace,sans-serif;
font-size:1.5em;
cursor:pointer;
color:grey;
user-select:none;
line-height:1;
text-align:center;
position:absolute;
top:10px;
right:10px;
}
#inbox-toggle.active { color:#007bff; }
/* Chevron */
#quick-capture-chevron {
position:absolute;
bottom:10px;
left:50%;
transform:translateX(-50%);
font-size:1.5em;
cursor:pointer;
color:#666;
}
#quick-capture-chevron:hover { color:#007bff; }
/* Mobile adjustments */
@media(max-width:820px){
#quick-capture-popover {
position:fixed !important;
top:0; left:0; width:100%; height:100%;
padding:15px;
margin:0; border:none; border-radius:0;
display:none; /* start hidden */
flex-direction:column;
z-index:1000;
}
#quick-capture-popover textarea {
font-size:1.3em;
padding:16px;
}
#save-button { bottom:16px; right:16px; padding:12px 20px; }
#inbox-toggle { top:auto; bottom:60px; right:20px; }
}
#note-view-modal { display:none; position:fixed; top:0; left:0; width:100%; height:100%; background:rgba(0,0,0,0.5); z-index:2000; justify-content:center; align-items:center; }
#note-view-content { background:var(--column-bg); padding:20px; border-radius:6px; max-width:500px; width:90%; max-height:80%; overflow:auto; box-shadow:0 2px 8px rgba(0,0,0,0.3); white-space:pre-wrap;}
#note-close { float:right; cursor:pointer; font-size:1.2em; color:#888;}
#note-close:hover { color:#000; }
</style>
</head>
<body>
<h2>Dashboard</h2>
<button id="quick-capture-btn">Quick Capture Note</button>
<div id="quick-capture-popover">
<form id="quick-capture-form" method="post" style="position:relative; height:100%; display:flex; flex-direction:column;">
<textarea id="note-body" name="note_body" placeholder="Type your note here..."></textarea>
<div id="inbox-toggle">✈</div>
<button type="submit" id="save-button" disabled>Save</button>
<input type="hidden" name="field_inbox" value="0">
<div id="quick-capture-chevron">▼</div>
</form>
</div>
<div id="note-view-modal">
<div id="note-view-content">
<span id="note-close">✕</span>
<h4 id="view-title"></h4>
<p id="view-body"></p>
<p><em id="view-created"></em></p>
</div>
</div>
<div class="columns">
<div class="column" id="inbox-column">
<h4>Inbox</h4>
<ul id="inbox-list">
<?php foreach ($inbox_notes as $note):
$created = $note['attributes']['created'] ?? '';
if ($created) { $dt = new DateTime($created); $created = $dt->format('M j, Y g:i A'); }
$body = $note['attributes']['body']['value'] ?? '';
?>
<li class="note-item" data-title="<?=htmlentities($note['attributes']['title'])?>" data-body="<?=htmlentities($body)?>" data-created="<?=$created?>"><?=htmlentities($note['attributes']['title'])." — $created"?></li>
<?php endforeach; ?>
</ul>
</div>
<div class="column" id="recent-column">
<h4>Recent</h4>
<ul id="recent-list">
<?php foreach ($recent_notes as $note):
$created = $note['attributes']['created'] ?? '';
if ($created) { $dt = new DateTime($created); $created = $dt->format('M j, Y g:i A'); }
$body = $note['attributes']['body']['value'] ?? '';
?>
<li class="note-item" data-title="<?=htmlentities($note['attributes']['title'])?>" data-body="<?=htmlentities($body)?>" data-created="<?=$created?>"><?=htmlentities($note['attributes']['title'])." — $created"?></li>
<?php endforeach; ?>
</ul>
</div>
<div class="column" id="all-column">
<h4>All</h4>
<ul id="all-list">
<?php foreach ($all_notes as $note):
$created = $note['attributes']['created'] ?? '';
if ($created) { $dt = new DateTime($created); $created = $dt->format('M j, Y g:i A'); }
$body = $note['attributes']['body']['value'] ?? '';
?>
<li class="note-item" data-title="<?=htmlentities($note['attributes']['title'])?>" data-body="<?=htmlentities($body)?>" data-created="<?=$created?>"><?=htmlentities($note['attributes']['title'])." — $created"?></li>
<?php endforeach; ?>
</ul>
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', function(){
const btn = document.getElementById('quick-capture-btn');
const popover = document.getElementById('quick-capture-popover');
const textarea = document.getElementById('note-body');
const saveBtn = document.getElementById('save-button');
const inboxToggle = document.getElementById('inbox-toggle');
const form = document.getElementById('quick-capture-form');
let inboxActive = false;
function isMobile() { return window.innerWidth <= 820; }
// Quick Capture toggle
btn.addEventListener('click', ()=>{
if(popover.style.display==='flex' || popover.style.display==='block'){
popover.style.display='none';
} else {
if(isMobile()){
popover.style.display='flex';
} else {
const rect = btn.getBoundingClientRect();
popover.style.top = rect.bottom + window.scrollY + 5 + 'px';
popover.style.left = rect.left + window.scrollX + 'px';
popover.style.display='block';
}
textarea.focus();
}
});
// Save button activation
textarea.addEventListener('input', ()=>{
if(textarea.value.trim()!==''){
saveBtn.disabled=false;
saveBtn.classList.add('active');
} else {
saveBtn.disabled=true;
saveBtn.classList.remove('active');
}
});
// Inbox toggle
inboxToggle.addEventListener('click', ()=>{
inboxActive = !inboxActive;
inboxToggle.classList.toggle('active', inboxActive);
form.querySelector('input[name="field_inbox"]').value = inboxActive?1:0;
});
// Note modal
const noteModal = document.getElementById('note-view-modal');
const viewTitle = document.getElementById('view-title');
const viewBody = document.getElementById('view-body');
const viewCreated = document.getElementById('view-created');
const noteClose = document.getElementById('note-close');
document.querySelectorAll('.column ul').forEach(ul => {
ul.addEventListener('click', e => {
const item = e.target.closest('.note-item');
if(!item) return;
viewTitle.textContent = item.dataset.title;
viewBody.textContent = item.dataset.body;
viewCreated.textContent = item.dataset.created;
noteModal.style.display='flex';
});
});
noteClose.addEventListener('click', ()=>{ noteModal.style.display='none'; });
noteModal.addEventListener('click', e=>{ if(e.target===noteModal) noteModal.style.display='none'; });
});
</script>
</body>
</html>