feat: add hidden flag to specials
This commit is contained in:
@@ -15,6 +15,7 @@ interface Special {
|
|||||||
launchDate?: string;
|
launchDate?: string;
|
||||||
endDate?: string;
|
endDate?: string;
|
||||||
curator?: string;
|
curator?: string;
|
||||||
|
hidden?: boolean;
|
||||||
_count?: {
|
_count?: {
|
||||||
songs: number;
|
songs: number;
|
||||||
};
|
};
|
||||||
@@ -119,6 +120,7 @@ export default function AdminPage({ params }: { params: { locale: string } }) {
|
|||||||
const [newSpecialLaunchDate, setNewSpecialLaunchDate] = useState('');
|
const [newSpecialLaunchDate, setNewSpecialLaunchDate] = useState('');
|
||||||
const [newSpecialEndDate, setNewSpecialEndDate] = useState('');
|
const [newSpecialEndDate, setNewSpecialEndDate] = useState('');
|
||||||
const [newSpecialCurator, setNewSpecialCurator] = useState('');
|
const [newSpecialCurator, setNewSpecialCurator] = useState('');
|
||||||
|
const [newSpecialHidden, setNewSpecialHidden] = useState(false);
|
||||||
|
|
||||||
const [editingSpecialId, setEditingSpecialId] = useState<number | null>(null);
|
const [editingSpecialId, setEditingSpecialId] = useState<number | null>(null);
|
||||||
const [editSpecialName, setEditSpecialName] = useState({ de: '', en: '' });
|
const [editSpecialName, setEditSpecialName] = useState({ de: '', en: '' });
|
||||||
@@ -129,6 +131,7 @@ export default function AdminPage({ params }: { params: { locale: string } }) {
|
|||||||
const [editSpecialLaunchDate, setEditSpecialLaunchDate] = useState('');
|
const [editSpecialLaunchDate, setEditSpecialLaunchDate] = useState('');
|
||||||
const [editSpecialEndDate, setEditSpecialEndDate] = useState('');
|
const [editSpecialEndDate, setEditSpecialEndDate] = useState('');
|
||||||
const [editSpecialCurator, setEditSpecialCurator] = useState('');
|
const [editSpecialCurator, setEditSpecialCurator] = useState('');
|
||||||
|
const [editSpecialHidden, setEditSpecialHidden] = useState(false);
|
||||||
|
|
||||||
// News state
|
// News state
|
||||||
const [news, setNews] = useState<News[]>([]);
|
const [news, setNews] = useState<News[]>([]);
|
||||||
@@ -393,6 +396,7 @@ export default function AdminPage({ params }: { params: { locale: string } }) {
|
|||||||
launchDate: newSpecialLaunchDate || null,
|
launchDate: newSpecialLaunchDate || null,
|
||||||
endDate: newSpecialEndDate || null,
|
endDate: newSpecialEndDate || null,
|
||||||
curator: newSpecialCurator || null,
|
curator: newSpecialCurator || null,
|
||||||
|
hidden: newSpecialHidden,
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
if (res.ok) {
|
if (res.ok) {
|
||||||
@@ -404,6 +408,7 @@ export default function AdminPage({ params }: { params: { locale: string } }) {
|
|||||||
setNewSpecialLaunchDate('');
|
setNewSpecialLaunchDate('');
|
||||||
setNewSpecialEndDate('');
|
setNewSpecialEndDate('');
|
||||||
setNewSpecialCurator('');
|
setNewSpecialCurator('');
|
||||||
|
setNewSpecialHidden(false);
|
||||||
fetchSpecials();
|
fetchSpecials();
|
||||||
} else {
|
} else {
|
||||||
const errorData = await res.json().catch(() => ({}));
|
const errorData = await res.json().catch(() => ({}));
|
||||||
@@ -491,6 +496,7 @@ export default function AdminPage({ params }: { params: { locale: string } }) {
|
|||||||
setEditSpecialLaunchDate(special.launchDate ? new Date(special.launchDate).toISOString().split('T')[0] : '');
|
setEditSpecialLaunchDate(special.launchDate ? new Date(special.launchDate).toISOString().split('T')[0] : '');
|
||||||
setEditSpecialEndDate(special.endDate ? new Date(special.endDate).toISOString().split('T')[0] : '');
|
setEditSpecialEndDate(special.endDate ? new Date(special.endDate).toISOString().split('T')[0] : '');
|
||||||
setEditSpecialCurator(special.curator || '');
|
setEditSpecialCurator(special.curator || '');
|
||||||
|
setEditSpecialHidden(special.hidden || false);
|
||||||
};
|
};
|
||||||
|
|
||||||
const saveEditedSpecial = async () => {
|
const saveEditedSpecial = async () => {
|
||||||
@@ -516,6 +522,7 @@ export default function AdminPage({ params }: { params: { locale: string } }) {
|
|||||||
launchDate: editSpecialLaunchDate || null,
|
launchDate: editSpecialLaunchDate || null,
|
||||||
endDate: editSpecialEndDate || null,
|
endDate: editSpecialEndDate || null,
|
||||||
curator: editSpecialCurator || null,
|
curator: editSpecialCurator || null,
|
||||||
|
hidden: editSpecialHidden,
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
if (res.ok) {
|
if (res.ok) {
|
||||||
@@ -1389,6 +1396,18 @@ export default function AdminPage({ params }: { params: { locale: string } }) {
|
|||||||
<label style={{ fontSize: '0.75rem', color: '#666' }}>{t('curator')}</label>
|
<label style={{ fontSize: '0.75rem', color: '#666' }}>{t('curator')}</label>
|
||||||
<input type="text" placeholder={t('curator')} value={newSpecialCurator} onChange={e => setNewSpecialCurator(e.target.value)} className="form-input" />
|
<input type="text" placeholder={t('curator')} value={newSpecialCurator} onChange={e => setNewSpecialCurator(e.target.value)} className="form-input" />
|
||||||
</div>
|
</div>
|
||||||
|
<div style={{ display: 'flex', flexDirection: 'column' }}>
|
||||||
|
<label style={{ fontSize: '0.75rem', color: '#666', visibility: 'hidden' }}>Hidden</label>
|
||||||
|
<label style={{ display: 'flex', alignItems: 'center', gap: '0.25rem', height: '38px', cursor: 'pointer' }}>
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
checked={newSpecialHidden}
|
||||||
|
onChange={e => setNewSpecialHidden(e.target.checked)}
|
||||||
|
style={{ width: '1rem', height: '1rem' }}
|
||||||
|
/>
|
||||||
|
Hidden
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
<button
|
<button
|
||||||
type="submit"
|
type="submit"
|
||||||
className="btn-primary"
|
className="btn-primary"
|
||||||
@@ -1418,7 +1437,7 @@ export default function AdminPage({ params }: { params: { locale: string } }) {
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<span>
|
<span>
|
||||||
{getLocalizedValue(special.name, activeTab)} ({special._count?.songs || 0})
|
{special.hidden && <span title="Hidden from navigation">👁️🗨️</span>} {getLocalizedValue(special.name, activeTab)} ({special._count?.songs || 0})
|
||||||
</span>
|
</span>
|
||||||
{special.subtitle && (
|
{special.subtitle && (
|
||||||
<span
|
<span
|
||||||
@@ -1508,6 +1527,18 @@ export default function AdminPage({ params }: { params: { locale: string } }) {
|
|||||||
<label style={{ fontSize: '0.75rem', color: '#666' }}>{t('curator')}</label>
|
<label style={{ fontSize: '0.75rem', color: '#666' }}>{t('curator')}</label>
|
||||||
<input type="text" value={editSpecialCurator} onChange={e => setEditSpecialCurator(e.target.value)} className="form-input" />
|
<input type="text" value={editSpecialCurator} onChange={e => setEditSpecialCurator(e.target.value)} className="form-input" />
|
||||||
</div>
|
</div>
|
||||||
|
<div style={{ display: 'flex', flexDirection: 'column' }}>
|
||||||
|
<label style={{ fontSize: '0.75rem', color: '#666', visibility: 'hidden' }}>Hidden</label>
|
||||||
|
<label style={{ display: 'flex', alignItems: 'center', gap: '0.25rem', height: '38px', cursor: 'pointer' }}>
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
checked={editSpecialHidden}
|
||||||
|
onChange={e => setEditSpecialHidden(e.target.checked)}
|
||||||
|
style={{ width: '1rem', height: '1rem' }}
|
||||||
|
/>
|
||||||
|
Hidden
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
<button
|
<button
|
||||||
onClick={saveEditedSpecial}
|
onClick={saveEditedSpecial}
|
||||||
className="btn-primary"
|
className="btn-primary"
|
||||||
|
|||||||
@@ -43,7 +43,9 @@ export default async function Home({
|
|||||||
const genres = await prisma.genre.findMany({
|
const genres = await prisma.genre.findMany({
|
||||||
where: { active: true },
|
where: { active: true },
|
||||||
});
|
});
|
||||||
const specials = await prisma.special.findMany();
|
const specials = await prisma.special.findMany({
|
||||||
|
where: { hidden: false },
|
||||||
|
});
|
||||||
|
|
||||||
// Sort in memory
|
// Sort in memory
|
||||||
genres.sort((a, b) => getLocalizedValue(a.name, locale).localeCompare(getLocalizedValue(b.name, locale)));
|
genres.sort((a, b) => getLocalizedValue(a.name, locale).localeCompare(getLocalizedValue(b.name, locale)));
|
||||||
|
|||||||
@@ -86,6 +86,7 @@ export default async function SpecialPage({ params }: PageProps) {
|
|||||||
specials.sort((a, b) => getLocalizedValue(a.name, locale).localeCompare(getLocalizedValue(b.name, locale)));
|
specials.sort((a, b) => getLocalizedValue(a.name, locale).localeCompare(getLocalizedValue(b.name, locale)));
|
||||||
|
|
||||||
const activeSpecials = specials.filter(s => {
|
const activeSpecials = specials.filter(s => {
|
||||||
|
if (s.hidden) return false;
|
||||||
const sStarted = !s.launchDate || s.launchDate <= now;
|
const sStarted = !s.launchDate || s.launchDate <= now;
|
||||||
const sEnded = s.endDate && s.endDate < now;
|
const sEnded = s.endDate && s.endDate < now;
|
||||||
return sStarted && !sEnded;
|
return sStarted && !sEnded;
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ interface Special {
|
|||||||
launchDate?: string;
|
launchDate?: string;
|
||||||
endDate?: string;
|
endDate?: string;
|
||||||
curator?: string;
|
curator?: string;
|
||||||
|
hidden?: boolean;
|
||||||
_count?: {
|
_count?: {
|
||||||
songs: number;
|
songs: number;
|
||||||
};
|
};
|
||||||
@@ -88,6 +89,7 @@ export default function AdminPage() {
|
|||||||
const [newSpecialLaunchDate, setNewSpecialLaunchDate] = useState('');
|
const [newSpecialLaunchDate, setNewSpecialLaunchDate] = useState('');
|
||||||
const [newSpecialEndDate, setNewSpecialEndDate] = useState('');
|
const [newSpecialEndDate, setNewSpecialEndDate] = useState('');
|
||||||
const [newSpecialCurator, setNewSpecialCurator] = useState('');
|
const [newSpecialCurator, setNewSpecialCurator] = useState('');
|
||||||
|
const [newSpecialHidden, setNewSpecialHidden] = useState(false);
|
||||||
|
|
||||||
const [editingSpecialId, setEditingSpecialId] = useState<number | null>(null);
|
const [editingSpecialId, setEditingSpecialId] = useState<number | null>(null);
|
||||||
const [editSpecialName, setEditSpecialName] = useState('');
|
const [editSpecialName, setEditSpecialName] = useState('');
|
||||||
@@ -97,6 +99,7 @@ export default function AdminPage() {
|
|||||||
const [editSpecialLaunchDate, setEditSpecialLaunchDate] = useState('');
|
const [editSpecialLaunchDate, setEditSpecialLaunchDate] = useState('');
|
||||||
const [editSpecialEndDate, setEditSpecialEndDate] = useState('');
|
const [editSpecialEndDate, setEditSpecialEndDate] = useState('');
|
||||||
const [editSpecialCurator, setEditSpecialCurator] = useState('');
|
const [editSpecialCurator, setEditSpecialCurator] = useState('');
|
||||||
|
const [editSpecialHidden, setEditSpecialHidden] = useState(false);
|
||||||
|
|
||||||
// News state
|
// News state
|
||||||
const [news, setNews] = useState<News[]>([]);
|
const [news, setNews] = useState<News[]>([]);
|
||||||
@@ -268,6 +271,7 @@ export default function AdminPage() {
|
|||||||
launchDate: newSpecialLaunchDate || null,
|
launchDate: newSpecialLaunchDate || null,
|
||||||
endDate: newSpecialEndDate || null,
|
endDate: newSpecialEndDate || null,
|
||||||
curator: newSpecialCurator || null,
|
curator: newSpecialCurator || null,
|
||||||
|
hidden: newSpecialHidden,
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
if (res.ok) {
|
if (res.ok) {
|
||||||
@@ -278,6 +282,7 @@ export default function AdminPage() {
|
|||||||
setNewSpecialLaunchDate('');
|
setNewSpecialLaunchDate('');
|
||||||
setNewSpecialEndDate('');
|
setNewSpecialEndDate('');
|
||||||
setNewSpecialCurator('');
|
setNewSpecialCurator('');
|
||||||
|
setNewSpecialHidden(false);
|
||||||
fetchSpecials();
|
fetchSpecials();
|
||||||
} else {
|
} else {
|
||||||
alert('Failed to create special');
|
alert('Failed to create special');
|
||||||
@@ -363,6 +368,7 @@ export default function AdminPage() {
|
|||||||
setEditSpecialLaunchDate(special.launchDate ? new Date(special.launchDate).toISOString().split('T')[0] : '');
|
setEditSpecialLaunchDate(special.launchDate ? new Date(special.launchDate).toISOString().split('T')[0] : '');
|
||||||
setEditSpecialEndDate(special.endDate ? new Date(special.endDate).toISOString().split('T')[0] : '');
|
setEditSpecialEndDate(special.endDate ? new Date(special.endDate).toISOString().split('T')[0] : '');
|
||||||
setEditSpecialCurator(special.curator || '');
|
setEditSpecialCurator(special.curator || '');
|
||||||
|
setEditSpecialHidden(special.hidden || false);
|
||||||
};
|
};
|
||||||
|
|
||||||
const saveEditedSpecial = async () => {
|
const saveEditedSpecial = async () => {
|
||||||
@@ -379,6 +385,7 @@ export default function AdminPage() {
|
|||||||
launchDate: editSpecialLaunchDate || null,
|
launchDate: editSpecialLaunchDate || null,
|
||||||
endDate: editSpecialEndDate || null,
|
endDate: editSpecialEndDate || null,
|
||||||
curator: editSpecialCurator || null,
|
curator: editSpecialCurator || null,
|
||||||
|
hidden: editSpecialHidden,
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
if (res.ok) {
|
if (res.ok) {
|
||||||
@@ -632,6 +639,15 @@ export default function AdminPage() {
|
|||||||
<div style={{ display: 'flex', flexDirection: 'column' }}>
|
<div style={{ display: 'flex', flexDirection: 'column' }}>
|
||||||
<label style={{ fontSize: '0.75rem', color: '#666' }}>Curator</label>
|
<label style={{ fontSize: '0.75rem', color: '#666' }}>Curator</label>
|
||||||
<input type="text" placeholder="Curator name" value={newSpecialCurator} onChange={e => setNewSpecialCurator(e.target.value)} className="form-input" />
|
<input type="text" placeholder="Curator name" value={newSpecialCurator} onChange={e => setNewSpecialCurator(e.target.value)} className="form-input" />
|
||||||
|
<label style={{ display: 'flex', alignItems: 'center', gap: '0.25rem', fontSize: '0.875rem', cursor: 'pointer', marginTop: '0.5rem' }}>
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
checked={newSpecialHidden}
|
||||||
|
onChange={e => setNewSpecialHidden(e.target.checked)}
|
||||||
|
style={{ width: '1rem', height: '1rem' }}
|
||||||
|
/>
|
||||||
|
Hidden Special (not in navigation)
|
||||||
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<button type="submit" className="btn-primary" style={{ height: '38px' }}>Add Special</button>
|
<button type="submit" className="btn-primary" style={{ height: '38px' }}>Add Special</button>
|
||||||
</div>
|
</div>
|
||||||
@@ -651,7 +667,7 @@ export default function AdminPage() {
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<span>
|
<span>
|
||||||
{special.name} ({special._count?.songs || 0})
|
{special.hidden && <span title="Hidden from navigation">👁️🗨️</span>} {special.name} ({special._count?.songs || 0})
|
||||||
</span>
|
</span>
|
||||||
{special.subtitle && (
|
{special.subtitle && (
|
||||||
<span
|
<span
|
||||||
@@ -711,6 +727,15 @@ export default function AdminPage() {
|
|||||||
<div style={{ display: 'flex', flexDirection: 'column' }}>
|
<div style={{ display: 'flex', flexDirection: 'column' }}>
|
||||||
<label style={{ fontSize: '0.75rem', color: '#666' }}>Curator</label>
|
<label style={{ fontSize: '0.75rem', color: '#666' }}>Curator</label>
|
||||||
<input type="text" value={editSpecialCurator} onChange={e => setEditSpecialCurator(e.target.value)} className="form-input" />
|
<input type="text" value={editSpecialCurator} onChange={e => setEditSpecialCurator(e.target.value)} className="form-input" />
|
||||||
|
<label style={{ display: 'flex', alignItems: 'center', gap: '0.25rem', fontSize: '0.875rem', cursor: 'pointer', marginTop: '0.5rem' }}>
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
checked={editSpecialHidden}
|
||||||
|
onChange={e => setEditSpecialHidden(e.target.checked)}
|
||||||
|
style={{ width: '1rem', height: '1rem' }}
|
||||||
|
/>
|
||||||
|
Hidden Special
|
||||||
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<button onClick={saveEditedSpecial} className="btn-primary" style={{ height: '38px' }}>Save</button>
|
<button onClick={saveEditedSpecial} className="btn-primary" style={{ height: '38px' }}>Save</button>
|
||||||
<button onClick={() => setEditingSpecialId(null)} className="btn-secondary" style={{ height: '38px' }}>Cancel</button>
|
<button onClick={() => setEditingSpecialId(null)} className="btn-secondary" style={{ height: '38px' }}>Cancel</button>
|
||||||
|
|||||||
@@ -43,18 +43,20 @@ export async function PUT(
|
|||||||
try {
|
try {
|
||||||
const { id } = await params;
|
const { id } = await params;
|
||||||
const specialId = parseInt(id);
|
const specialId = parseInt(id);
|
||||||
const { name, maxAttempts, unlockSteps, launchDate, endDate, curator } = await request.json();
|
const { name, maxAttempts, unlockSteps, launchDate, endDate, curator, hidden } = await request.json();
|
||||||
|
|
||||||
|
const updateData: any = {};
|
||||||
|
if (name !== undefined) updateData.name = name;
|
||||||
|
if (maxAttempts !== undefined) updateData.maxAttempts = maxAttempts;
|
||||||
|
if (unlockSteps !== undefined) updateData.unlockSteps = typeof unlockSteps === 'string' ? unlockSteps : JSON.stringify(unlockSteps);
|
||||||
|
if (launchDate !== undefined) updateData.launchDate = launchDate ? new Date(launchDate) : null;
|
||||||
|
if (endDate !== undefined) updateData.endDate = endDate ? new Date(endDate) : null;
|
||||||
|
if (curator !== undefined) updateData.curator = curator || null;
|
||||||
|
if (hidden !== undefined) updateData.hidden = Boolean(hidden);
|
||||||
|
|
||||||
const special = await prisma.special.update({
|
const special = await prisma.special.update({
|
||||||
where: { id: specialId },
|
where: { id: specialId },
|
||||||
data: {
|
data: updateData
|
||||||
name,
|
|
||||||
maxAttempts,
|
|
||||||
unlockSteps: typeof unlockSteps === 'string' ? unlockSteps : JSON.stringify(unlockSteps),
|
|
||||||
launchDate: launchDate ? new Date(launchDate) : null,
|
|
||||||
endDate: endDate ? new Date(endDate) : null,
|
|
||||||
curator: curator || null,
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return NextResponse.json(special);
|
return NextResponse.json(special);
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ export async function POST(request: Request) {
|
|||||||
const authError = await requireAdminAuth(request as any);
|
const authError = await requireAdminAuth(request as any);
|
||||||
if (authError) return authError;
|
if (authError) return authError;
|
||||||
|
|
||||||
const { name, subtitle, maxAttempts = 7, unlockSteps = '[2,4,7,11,16,30,60]', launchDate, endDate, curator } = await request.json();
|
const { name, subtitle, maxAttempts = 7, unlockSteps = '[2,4,7,11,16,30,60]', launchDate, endDate, curator, hidden = false } = await request.json();
|
||||||
if (!name) {
|
if (!name) {
|
||||||
return NextResponse.json({ error: 'Name is required' }, { status: 400 });
|
return NextResponse.json({ error: 'Name is required' }, { status: 400 });
|
||||||
}
|
}
|
||||||
@@ -68,6 +68,7 @@ export async function POST(request: Request) {
|
|||||||
launchDate: launchDate ? new Date(launchDate) : null,
|
launchDate: launchDate ? new Date(launchDate) : null,
|
||||||
endDate: endDate ? new Date(endDate) : null,
|
endDate: endDate ? new Date(endDate) : null,
|
||||||
curator: curator || null,
|
curator: curator || null,
|
||||||
|
hidden: Boolean(hidden),
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
return NextResponse.json(special);
|
return NextResponse.json(special);
|
||||||
@@ -91,7 +92,7 @@ export async function PUT(request: Request) {
|
|||||||
const authError = await requireAdminAuth(request as any);
|
const authError = await requireAdminAuth(request as any);
|
||||||
if (authError) return authError;
|
if (authError) return authError;
|
||||||
|
|
||||||
const { id, name, subtitle, maxAttempts, unlockSteps, launchDate, endDate, curator } = await request.json();
|
const { id, name, subtitle, maxAttempts, unlockSteps, launchDate, endDate, curator, hidden } = await request.json();
|
||||||
if (!id) {
|
if (!id) {
|
||||||
return NextResponse.json({ error: 'ID required' }, { status: 400 });
|
return NextResponse.json({ error: 'ID required' }, { status: 400 });
|
||||||
}
|
}
|
||||||
@@ -119,6 +120,7 @@ export async function PUT(request: Request) {
|
|||||||
if (launchDate !== undefined) updateData.launchDate = launchDate ? new Date(launchDate) : null;
|
if (launchDate !== undefined) updateData.launchDate = launchDate ? new Date(launchDate) : null;
|
||||||
if (endDate !== undefined) updateData.endDate = endDate ? new Date(endDate) : null;
|
if (endDate !== undefined) updateData.endDate = endDate ? new Date(endDate) : null;
|
||||||
if (curator !== undefined) updateData.curator = curator || null;
|
if (curator !== undefined) updateData.curator = curator || null;
|
||||||
|
if (hidden !== undefined) updateData.hidden = Boolean(hidden);
|
||||||
|
|
||||||
const updated = await prisma.special.update({
|
const updated = await prisma.special.update({
|
||||||
where: { id: Number(id) },
|
where: { id: Number(id) },
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
-- RedefineTables
|
||||||
|
PRAGMA defer_foreign_keys=ON;
|
||||||
|
PRAGMA foreign_keys=OFF;
|
||||||
|
CREATE TABLE "new_Special" (
|
||||||
|
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
||||||
|
"name" JSONB NOT NULL,
|
||||||
|
"subtitle" JSONB,
|
||||||
|
"maxAttempts" INTEGER NOT NULL DEFAULT 7,
|
||||||
|
"unlockSteps" TEXT NOT NULL,
|
||||||
|
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
"launchDate" DATETIME,
|
||||||
|
"endDate" DATETIME,
|
||||||
|
"curator" TEXT,
|
||||||
|
"hidden" BOOLEAN NOT NULL DEFAULT false
|
||||||
|
);
|
||||||
|
INSERT INTO "new_Special" ("createdAt", "curator", "endDate", "id", "launchDate", "maxAttempts", "name", "subtitle", "unlockSteps") SELECT "createdAt", "curator", "endDate", "id", "launchDate", "maxAttempts", "name", "subtitle", "unlockSteps" FROM "Special";
|
||||||
|
DROP TABLE "Special";
|
||||||
|
ALTER TABLE "new_Special" RENAME TO "Special";
|
||||||
|
PRAGMA foreign_keys=ON;
|
||||||
|
PRAGMA defer_foreign_keys=OFF;
|
||||||
@@ -47,6 +47,7 @@ model Special {
|
|||||||
launchDate DateTime?
|
launchDate DateTime?
|
||||||
endDate DateTime?
|
endDate DateTime?
|
||||||
curator String?
|
curator String?
|
||||||
|
hidden Boolean @default(false)
|
||||||
songs SpecialSong[]
|
songs SpecialSong[]
|
||||||
puzzles DailyPuzzle[]
|
puzzles DailyPuzzle[]
|
||||||
news News[]
|
news News[]
|
||||||
|
|||||||
Reference in New Issue
Block a user