first commit
Some checks failed
Deploy to Private Server / deploy (push) Failing after 2s

This commit is contained in:
2025-12-24 11:49:29 +07:00
commit 97e902ec50
19 changed files with 4897 additions and 0 deletions

View File

@@ -0,0 +1,23 @@
import { Select } from 'antd';
export default function CalculatorMode({ value, onChange }) {
return (
<div className="form-row">
<label htmlFor="calculator-mode" className="form-label">
Calculate
</label>
<Select
id="calculator-mode"
value={value}
onChange={onChange}
size="large"
style={{ width: '100%' }}
options={[
{ value: 'shooting-interval', label: 'Shooting interval' },
{ value: 'clip-length', label: 'Clip length' },
{ value: 'event-duration', label: 'Event duration' },
]}
/>
</div>
);
}

View File

@@ -0,0 +1,9 @@
export default function Header() {
return (
<header className="header">
<div className="container">
<h1>TIMELAPSE CALCULATOR</h1>
</div>
</header>
);
}

View File

@@ -0,0 +1,25 @@
import { InputNumber } from 'antd';
export default function NumberInput({ label, value, onChange, unit, min = 0, step = 1 }) {
const handleChange = (newValue) => {
const numValue = Math.max(min, newValue || 0);
onChange(numValue);
};
return (
<div className="form-row">
<label className="form-label">{label}</label>
<InputNumber
value={value}
onChange={handleChange}
min={min}
step={step}
placeholder="0"
addonAfter={unit}
size="large"
style={{ width: '100%' }}
controls={false}
/>
</div>
);
}

View File

@@ -0,0 +1,54 @@
import { Statistic, Row, Col } from 'antd';
export default function Results({ shootingInterval, numberOfPhotos, totalMemory }) {
const formatTime = (seconds) => {
if (seconds < 60) {
return `${seconds.toFixed(0)}s`;
} else if (seconds < 3600) {
const mins = Math.floor(seconds / 60);
const secs = Math.floor(seconds % 60);
return `${mins}m ${secs}s`;
} else {
const hours = Math.floor(seconds / 3600);
const mins = Math.floor((seconds % 3600) / 60);
const secs = Math.floor(seconds % 60);
return `${hours}h ${mins}m ${secs}s`;
}
};
const formatMemory = (mb) => {
if (mb < 1024) {
return `${mb.toFixed(2)}MB`;
} else {
return `${(mb / 1024).toFixed(2)}GB`;
}
};
return (
<div className="results-section">
<Row gutter={[16, 16]}>
<Col xs={24} sm={8}>
<Statistic
title="Shooting interval"
value={formatTime(shootingInterval)}
valueStyle={{ color: '#2C3E50', fontSize: '1.5rem', fontWeight: 600 }}
/>
</Col>
<Col xs={24} sm={8}>
<Statistic
title="Number of photos"
value={numberOfPhotos}
valueStyle={{ color: '#2C3E50', fontSize: '1.5rem', fontWeight: 600 }}
/>
</Col>
<Col xs={24} sm={8}>
<Statistic
title="Total memory usage"
value={formatMemory(totalMemory)}
valueStyle={{ color: '#2C3E50', fontSize: '1.5rem', fontWeight: 600 }}
/>
</Col>
</Row>
</div>
);
}

View File

@@ -0,0 +1,53 @@
import { InputNumber, Space } from 'antd';
export default function TimeInput({ label, hours, minutes, seconds, onChange }) {
const handleChange = (field, value) => {
// Ensure non-negative values
const numValue = Math.max(0, value || 0);
onChange({
hours: field === 'hours' ? numValue : hours,
minutes: field === 'minutes' ? numValue : minutes,
seconds: field === 'seconds' ? numValue : seconds,
});
};
return (
<div className="form-row">
<label className="form-label">{label}</label>
<Space.Compact style={{ width: '100%' }} size="large">
<InputNumber
value={hours}
onChange={(value) => handleChange('hours', value)}
min={0}
placeholder="0"
addonAfter="h"
size="large"
style={{ width: '33.33%' }}
controls={false}
/>
<InputNumber
value={minutes}
onChange={(value) => handleChange('minutes', value)}
min={0}
max={59}
placeholder="0"
addonAfter="m"
size="large"
style={{ width: '33.33%' }}
controls={false}
/>
<InputNumber
value={seconds}
onChange={(value) => handleChange('seconds', value)}
min={0}
max={59}
placeholder="0"
addonAfter="s"
size="large"
style={{ width: '33.34%' }}
controls={false}
/>
</Space.Compact>
</div>
);
}