New: Hero Page und Navigation

This commit is contained in:
2024-10-04 16:46:22 +02:00
parent e2902457e2
commit fd5aa79278
45 changed files with 1804 additions and 1310 deletions

View File

@ -0,0 +1,7 @@
-- CreateTable
CREATE TABLE "Nachhilfeangebot" (
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
"subject" TEXT NOT NULL,
"currentClass" TEXT NOT NULL,
"cost" DECIMAL NOT NULL
);

View File

@ -0,0 +1,22 @@
/*
Warnings:
- Added the required column `userId` to the `Nachhilfeangebot` table without a default value. This is not possible if the table is not empty.
*/
-- RedefineTables
PRAGMA defer_foreign_keys=ON;
PRAGMA foreign_keys=OFF;
CREATE TABLE "new_Nachhilfeangebot" (
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
"subject" TEXT NOT NULL,
"currentClass" TEXT NOT NULL,
"cost" DECIMAL NOT NULL,
"userId" INTEGER NOT NULL,
CONSTRAINT "Nachhilfeangebot_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User" ("id") ON DELETE RESTRICT ON UPDATE CASCADE
);
INSERT INTO "new_Nachhilfeangebot" ("cost", "currentClass", "id", "subject") SELECT "cost", "currentClass", "id", "subject" FROM "Nachhilfeangebot";
DROP TABLE "Nachhilfeangebot";
ALTER TABLE "new_Nachhilfeangebot" RENAME TO "Nachhilfeangebot";
PRAGMA foreign_keys=ON;
PRAGMA defer_foreign_keys=OFF;

View File

@ -24,18 +24,19 @@ model UserExample {
}
model User {
id Int @id @default(autoincrement())
email String @unique
id Int @id @default(autoincrement())
email String @unique
firstName String?
lastName String?
hashedPassword String?
salt String?
identites Identity[]
resetToken String?
resetTokenExpiresAt DateTime?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
roles String @default("user")
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
roles String @default("user")
identites Identity[]
Nachhilfeangebot Nachhilfeangebot[]
}
model Identity {
@ -61,3 +62,12 @@ model Post {
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
model Nachhilfeangebot {
id Int @id @default(autoincrement())
subject String
currentClass String
cost Decimal
userId Int
user User @relation(fields: [userId], references: [id])
}

View File

@ -25,6 +25,7 @@ export const handler = async (
context: Context
) => {
const forgotPasswordOptions: DbAuthHandlerOptions['forgotPassword'] = {
enabled: false,
// handler() is invoked after verifying that a user was found with the given
// username. This is where you can send the user an email with a link to
// reset their password. With the default dbAuth routes and field names, the
@ -75,6 +76,7 @@ export const handler = async (
// didn't validate their email yet), throw an error and it will be returned
// by the `logIn()` function from `useAuth()` in the form of:
// `{ message: 'Error message' }`
enabled: false,
handler: (user) => {
return user
},
@ -100,6 +102,7 @@ export const handler = async (
handler: (_user) => {
return true
},
enabled: false,
// If `false` then the new password MUST be different from the current one
allowReusedPassword: true,
@ -139,6 +142,7 @@ export const handler = async (
//
// If this returns anything else, it will be returned by the
// `signUp()` function in the form of: `{ message: 'String here' }`.
enabled: false,
handler: ({
username,
hashedPassword,

View File

@ -0,0 +1,36 @@
export const schema = gql`
type Identity {
id: Int!
provider: String!
# uid: String!
userId: Int!
user: User!
# accessToken: String
# scope: String
lastLoginAt: DateTime!
createdAt: DateTime!
updatedAt: DateTime!
}
type Query {
identities: [Identity!]! @requireAuth
}
input CreateIdentityInput {
provider: String!
uid: String!
userId: Int!
accessToken: String
scope: String
lastLoginAt: DateTime!
}
input UpdateIdentityInput {
provider: String
uid: String
userId: Int
accessToken: String
scope: String
lastLoginAt: DateTime
}
`

View File

@ -0,0 +1,37 @@
export const schema = gql`
type Nachhilfeangebot {
id: Int!
subject: String!
currentClass: String!
cost: Float!
user: User!
}
type Query {
nachhilfeangebots: [Nachhilfeangebot!]! @requireAuth
nachhilfeangebot(id: Int!): Nachhilfeangebot @requireAuth
}
input CreateNachhilfeangebotInput {
subject: String!
currentClass: String!
cost: Float!
}
input UpdateNachhilfeangebotInput {
subject: String
currentClass: String
cost: Float
}
type Mutation {
createNachhilfeangebot(
input: CreateNachhilfeangebotInput!
): Nachhilfeangebot! @requireAuth
updateNachhilfeangebot(
id: Int!
input: UpdateNachhilfeangebotInput!
): Nachhilfeangebot! @requireAuth
deleteNachhilfeangebot(id: Int!): Nachhilfeangebot! @requireAuth
}
`

View File

@ -0,0 +1,43 @@
export const schema = gql`
type User {
id: Int!
email: String!
firstName: String
lastName: String
# hashedPassword: String
# salt: String
# resetToken: String
# resetTokenExpiresAt: DateTime
createdAt: DateTime!
updatedAt: DateTime!
roles: String!
identites: [Identity]!
Nachhilfeangebot: [Nachhilfeangebot]!
}
type Query {
users: [User!]! @requireAuth
}
input CreateUserInput {
email: String!
firstName: String
lastName: String
hashedPassword: String
salt: String
resetToken: String
resetTokenExpiresAt: DateTime
roles: String!
}
input UpdateUserInput {
email: String
firstName: String
lastName: String
hashedPassword: String
salt: String
resetToken: String
resetTokenExpiresAt: DateTime
roles: String
}
`

View File

@ -36,7 +36,13 @@ export const getCurrentUser = async (session: Decoded) => {
return await db.user.findUnique({
where: { id: session.id },
select: { id: true, email: true, roles: true },
select: {
id: true,
email: true,
roles: true,
firstName: true,
lastName: true,
},
})
}

View File

@ -0,0 +1,35 @@
import type { Prisma, Identity } from '@prisma/client'
import type { ScenarioData } from '@redwoodjs/testing/api'
export const standard = defineScenario<Prisma.IdentityCreateArgs>({
identity: {
one: {
data: {
provider: 'String',
uid: 'String',
updatedAt: '2024-10-04T12:47:55.457Z',
user: {
create: {
email: 'String3211260',
updatedAt: '2024-10-04T12:47:55.457Z',
},
},
},
},
two: {
data: {
provider: 'String',
uid: 'String',
updatedAt: '2024-10-04T12:47:55.457Z',
user: {
create: {
email: 'String2559297',
updatedAt: '2024-10-04T12:47:55.457Z',
},
},
},
},
},
})
export type StandardScenario = ScenarioData<Identity, 'identity'>

View File

@ -0,0 +1,18 @@
import type { Identity } from '@prisma/client'
import { identities } from './identities'
import type { StandardScenario } from './identities.scenarios'
// Generated boilerplate tests do not account for all circumstances
// and can fail without adjustments, e.g. Float.
// Please refer to the RedwoodJS Testing Docs:
// https://redwoodjs.com/docs/testing#testing-services
// https://redwoodjs.com/docs/testing#jest-expect-type-considerations
describe('identities', () => {
scenario('returns all identities', async (scenario: StandardScenario) => {
const result = await identities()
expect(result.length).toEqual(Object.keys(scenario.identity).length)
})
})

View File

@ -0,0 +1,19 @@
import type { QueryResolvers, IdentityRelationResolvers } from 'types/graphql'
import { db } from 'src/lib/db'
export const identities: QueryResolvers['identities'] = () => {
return db.identity.findMany()
}
export const identity: QueryResolvers['identity'] = ({ id }) => {
return db.identity.findUnique({
where: { id },
})
}
export const Identity: IdentityRelationResolvers = {
user: (_obj, { root }) => {
return db.identity.findUnique({ where: { id: root?.id } }).user()
},
}

View File

@ -0,0 +1,26 @@
import type { Prisma, Nachhilfeangebot } from '@prisma/client'
import type { ScenarioData } from '@redwoodjs/testing/api'
export const standard = defineScenario<Prisma.NachhilfeangebotCreateArgs>({
nachhilfeangebot: {
one: {
data: {
subject: 'String',
currentClass: 'String',
cost: 9626711.68060984,
},
},
two: {
data: {
subject: 'String',
currentClass: 'String',
cost: 3400746.9395209556,
},
},
},
})
export type StandardScenario = ScenarioData<
Nachhilfeangebot,
'nachhilfeangebot'
>

View File

@ -0,0 +1,75 @@
import { Prisma, Nachhilfeangebot } from '@prisma/client'
import {
nachhilfeangebots,
nachhilfeangebot,
createNachhilfeangebot,
updateNachhilfeangebot,
deleteNachhilfeangebot,
} from './nachhilfeangebots'
import type { StandardScenario } from './nachhilfeangebots.scenarios'
// Generated boilerplate tests do not account for all circumstances
// and can fail without adjustments, e.g. Float.
// Please refer to the RedwoodJS Testing Docs:
// https://redwoodjs.com/docs/testing#testing-services
// https://redwoodjs.com/docs/testing#jest-expect-type-considerations
describe('nachhilfeangebots', () => {
scenario(
'returns all nachhilfeangebots',
async (scenario: StandardScenario) => {
const result = await nachhilfeangebots()
expect(result.length).toEqual(
Object.keys(scenario.nachhilfeangebot).length
)
}
)
scenario(
'returns a single nachhilfeangebot',
async (scenario: StandardScenario) => {
const result = await nachhilfeangebot({
id: scenario.nachhilfeangebot.one.id,
})
expect(result).toEqual(scenario.nachhilfeangebot.one)
}
)
scenario('creates a nachhilfeangebot', async () => {
const result = await createNachhilfeangebot({
input: {
subject: 'String',
currentClass: 'String',
cost: 3443924.824820386,
},
})
expect(result.subject).toEqual('String')
expect(result.currentClass).toEqual('String')
expect(result.cost).toEqual(new Prisma.Decimal(3443924.824820386))
})
scenario('updates a nachhilfeangebot', async (scenario: StandardScenario) => {
const original = (await nachhilfeangebot({
id: scenario.nachhilfeangebot.one.id,
})) as Nachhilfeangebot
const result = await updateNachhilfeangebot({
id: original.id,
input: { subject: 'String2' },
})
expect(result.subject).toEqual('String2')
})
scenario('deletes a nachhilfeangebot', async (scenario: StandardScenario) => {
const original = (await deleteNachhilfeangebot({
id: scenario.nachhilfeangebot.one.id,
})) as Nachhilfeangebot
const result = await nachhilfeangebot({ id: original.id })
expect(result).toEqual(null)
})
})

View File

@ -0,0 +1,43 @@
import type { QueryResolvers, MutationResolvers } from 'types/graphql'
import { db } from 'src/lib/db'
export const nachhilfeangebots: QueryResolvers['nachhilfeangebots'] = () => {
return db.nachhilfeangebot.findMany()
}
export const nachhilfeangebot: QueryResolvers['nachhilfeangebot'] = ({
id,
}) => {
return {
...db.nachhilfeangebot.findUnique({
where: { id },
}),
user: db.nachhilfeangebot.findUnique({ where: { id } }).user(),
}
}
export const createNachhilfeangebot: MutationResolvers['createNachhilfeangebot'] =
({ input }) => {
return db.nachhilfeangebot.create({
data: {
...input,
userId: context.currentUser.id,
},
})
}
export const updateNachhilfeangebot: MutationResolvers['updateNachhilfeangebot'] =
({ id, input }) => {
return db.nachhilfeangebot.update({
data: input,
where: { id },
})
}
export const deleteNachhilfeangebot: MutationResolvers['deleteNachhilfeangebot'] =
({ id }) => {
return db.nachhilfeangebot.delete({
where: { id },
})
}

View File

@ -0,0 +1,15 @@
import type { Prisma, User } from '@prisma/client'
import type { ScenarioData } from '@redwoodjs/testing/api'
export const standard = defineScenario<Prisma.UserCreateArgs>({
user: {
one: {
data: { email: 'String5874784', updatedAt: '2024-10-04T12:47:22.490Z' },
},
two: {
data: { email: 'String7499025', updatedAt: '2024-10-04T12:47:22.490Z' },
},
},
})
export type StandardScenario = ScenarioData<User, 'user'>

View File

@ -0,0 +1,18 @@
import type { User } from '@prisma/client'
import { users } from './users'
import type { StandardScenario } from './users.scenarios'
// Generated boilerplate tests do not account for all circumstances
// and can fail without adjustments, e.g. Float.
// Please refer to the RedwoodJS Testing Docs:
// https://redwoodjs.com/docs/testing#testing-services
// https://redwoodjs.com/docs/testing#jest-expect-type-considerations
describe('users', () => {
scenario('returns all users', async (scenario: StandardScenario) => {
const result = await users()
expect(result.length).toEqual(Object.keys(scenario.user).length)
})
})

View File

@ -0,0 +1,22 @@
import type { QueryResolvers, UserRelationResolvers } from 'types/graphql'
import { db } from 'src/lib/db'
export const users: QueryResolvers['users'] = () => {
return db.user.findMany()
}
export const user: QueryResolvers['user'] = ({ id }) => {
return db.user.findUnique({
where: { id },
})
}
export const User: UserRelationResolvers = {
identites: (_obj, { root }) => {
return db.user.findUnique({ where: { id: root?.id } }).identites()
},
Nachhilfeangebot: (_obj, { root }) => {
return db.user.findUnique({ where: { id: root?.id } }).Nachhilfeangebot()
},
}