Skip to content
Draft
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
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,16 @@
# base44-zip
base 44 app

## File Upload Feature

This application provides a simple file upload interface with the following features:

- **Drag and Drop**: Drag files directly onto the upload area
- **Click to Browse**: Click the upload area to open a file browser
- **Multiple Files**: Upload multiple files at once
- **File Preview**: See file names and sizes before uploading
- **Remove Files**: Remove files from the queue before uploading

### Usage

Open `index.html` in a web browser to use the file upload interface.
313 changes: 313 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,313 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Base44 - File Upload</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}

body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
padding: 20px;
}

.container {
background: white;
border-radius: 16px;
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.2);
padding: 40px;
max-width: 500px;
width: 100%;
}

h1 {
color: #333;
margin-bottom: 8px;
font-size: 28px;
}

.subtitle {
color: #666;
margin-bottom: 30px;
}

.upload-area {
border: 2px dashed #ccc;
border-radius: 12px;
padding: 40px 20px;
text-align: center;
cursor: pointer;
transition: all 0.3s ease;
margin-bottom: 20px;
}

.upload-area:hover {
border-color: #667eea;
background: #f8f9ff;
}

.upload-area.dragover {
border-color: #667eea;
background: #f0f2ff;
}

.upload-icon {
font-size: 48px;
margin-bottom: 16px;
}

.upload-text {
color: #666;
margin-bottom: 8px;
}

.upload-hint {
color: #999;
font-size: 14px;
}

#fileInput {
display: none;
}

.file-list {
margin-top: 20px;
}

.file-item {
display: flex;
align-items: center;
padding: 12px;
background: #f8f9fa;
border-radius: 8px;
margin-bottom: 10px;
}

.file-icon {
font-size: 24px;
margin-right: 12px;
}

.file-info {
flex: 1;
}

.file-name {
color: #333;
font-weight: 500;
}

.file-size {
color: #999;
font-size: 13px;
}

.file-remove {
background: #ff4757;
color: white;
border: none;
border-radius: 6px;
padding: 6px 12px;
cursor: pointer;
font-size: 13px;
}

.file-remove:hover {
background: #ff3344;
}

.upload-btn {
width: 100%;
padding: 14px;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
border: none;
border-radius: 8px;
font-size: 16px;
font-weight: 600;
cursor: pointer;
margin-top: 20px;
transition: transform 0.2s ease;
}

.upload-btn:hover {
transform: translateY(-2px);
}

.upload-btn:disabled {
opacity: 0.6;
cursor: not-allowed;
transform: none;
}

.message {
margin-top: 15px;
padding: 12px;
border-radius: 8px;
text-align: center;
display: none;
}

.message.success {
display: block;
background: #d4edda;
color: #155724;
}

.message.error {
display: block;
background: #f8d7da;
color: #721c24;
}
</style>
</head>
<body>
<div class="container">
<h1><span aria-hidden="true">📁</span> File Upload</h1>
<p class="subtitle">Upload your files easily</p>

<div class="upload-area" id="uploadArea">
<div class="upload-icon" aria-hidden="true">☁️</div>
<p class="upload-text">Drag and drop files here</p>
<p class="upload-hint">or click to browse</p>
</div>

<input type="file" id="fileInput" multiple>

<div class="file-list" id="fileList"></div>

<button class="upload-btn" id="uploadBtn" disabled>Upload Files</button>

<div class="message" id="message"></div>
</div>

<script>
const uploadArea = document.getElementById('uploadArea');
const fileInput = document.getElementById('fileInput');
const fileList = document.getElementById('fileList');
const uploadBtn = document.getElementById('uploadBtn');
const message = document.getElementById('message');

let selectedFiles = [];
let dragCounter = 0;

// Click to open file dialog
uploadArea.addEventListener('click', () => {
fileInput.click();
});

// Handle file selection
fileInput.addEventListener('change', (e) => {
handleFiles(e.target.files);
});

// Drag and drop handlers
uploadArea.addEventListener('dragenter', (e) => {
e.preventDefault();
dragCounter++;
uploadArea.classList.add('dragover');
});

uploadArea.addEventListener('dragover', (e) => {
e.preventDefault();
});

uploadArea.addEventListener('dragleave', (e) => {
e.preventDefault();
dragCounter--;
if (dragCounter === 0) {
uploadArea.classList.remove('dragover');
}
});

uploadArea.addEventListener('drop', (e) => {
e.preventDefault();
dragCounter = 0;
uploadArea.classList.remove('dragover');
handleFiles(e.dataTransfer.files);
});

function handleFiles(files) {
for (let file of files) {
if (!selectedFiles.some(f => f.name === file.name && f.size === file.size && f.lastModified === file.lastModified)) {
selectedFiles.push(file);
}
}
renderFileList();
updateUploadButton();
}

function renderFileList() {
fileList.innerHTML = '';
selectedFiles.forEach((file, index) => {
const fileItem = document.createElement('div');
fileItem.className = 'file-item';
fileItem.innerHTML = `
<span class="file-icon" aria-hidden="true">📄</span>
<div class="file-info">
<div class="file-name">${escapeHtml(file.name)}</div>
<div class="file-size">${formatFileSize(file.size)}</div>
</div>
<button class="file-remove" data-index="${index}">Remove</button>
`;
fileList.appendChild(fileItem);
});

// Add remove handlers
document.querySelectorAll('.file-remove').forEach(btn => {
btn.addEventListener('click', (e) => {
const index = parseInt(e.target.getAttribute('data-index'));
selectedFiles.splice(index, 1);
renderFileList();
updateUploadButton();
});
});
}

function updateUploadButton() {
uploadBtn.disabled = selectedFiles.length === 0;
}

function formatFileSize(bytes) {
if (bytes === 0) return '0 Bytes';
const k = 1024;
const sizes = ['Bytes', 'KB', 'MB', 'GB'];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
}

function escapeHtml(text) {
const div = document.createElement('div');
div.textContent = text;
return div.innerHTML;
}

// Handle upload button click
uploadBtn.addEventListener('click', () => {
if (selectedFiles.length === 0) return;

// Show success message (in a real app, this would upload to a server)
showMessage('success', `${selectedFiles.length} file(s) ready for upload!`);

// In a real implementation, you would send files to a server here
// For now, we just show a success message
console.log('Files to upload:', selectedFiles);
});

function showMessage(type, text) {
message.className = `message ${type}`;
message.textContent = text;
}
</script>
</body>
</html>