[🏁 #2] Starter pack wizard (#4266)

* minimal landing page

add a minimal gate

remove overlap row

add bg to avatar set

implement basic mock up

add header of mock

add route

* add navigation

* create starter pack landing page

* add state reducer

* make value an array

* implement state w/ steps

* add back the flex

* view header back button

* add button text

* add button text

* add details screen

* add button states

* proper use of button

* oops

* rm extra state

* use keyboard aware scrollview

* rm log

* remove some stuff

* remove avatar from landing

* add list for profiles

* add profile card w/ button

* add feeds

* add processing state

* support editing a pack

* fix undefined error

* add desktop props

* add entire profile to state

* scope the profile list better

* scoping

* add key extractor to feeds

* add fab

* add icon to details

* changes

* add dialog for adding profiles

* remove log

* rm unused iports

* fix nav type
This commit is contained in:
Hailey
2024-06-02 18:14:08 -07:00
committed by GitHub
parent cb581bffd1
commit 30686702a6
18 changed files with 934 additions and 2 deletions
+137
View File
@@ -0,0 +1,137 @@
import React from 'react'
import {AppBskyActorDefs} from '@atproto/api'
const steps = ['Landing', 'Details', 'Profiles', 'Feeds'] as const
type Step = (typeof steps)[number]
type Action =
| {type: 'Next'}
| {type: 'Back'}
| {type: 'SetCanNext'; canNext: boolean}
| {type: 'SetName'; name: string}
| {type: 'SetDescription'; description: string}
| {type: 'AddProfile'; profile: AppBskyActorDefs.ProfileViewBasic}
| {type: 'RemoveProfile'; profileDid: string}
| {type: 'AddFeed'; uri: string}
| {type: 'RemoveFeed'; uri: string}
| {type: 'SetProcessing'; processing: boolean}
interface State {
canNext: boolean
currentStep: Step
name?: string
description?: string
avatar?: string
profiles: AppBskyActorDefs.ProfileViewBasic[]
feedUris: string[]
processing: boolean
}
type TStateContext = [State, (action: Action) => void]
const StateContext = React.createContext<TStateContext>([
{} as State,
(_: Action) => {},
])
export const useWizardState = () => React.useContext(StateContext)
function reducer(state: State, action: Action): State {
let updatedState = state
// -- Navigation
if (action.type === 'Next' && state.currentStep !== 'Feeds') {
const currentIndex = steps.indexOf(state.currentStep)
updatedState = {...state, currentStep: steps[currentIndex + 1]}
} else if (action.type === 'Back' && state.currentStep !== 'Landing') {
const currentIndex = steps.indexOf(state.currentStep)
updatedState = {...state, currentStep: steps[currentIndex - 1]}
}
switch (action.type) {
case 'SetName':
updatedState = {...state, name: action.name}
break
case 'SetDescription':
updatedState = {...state, description: action.description}
break
case 'AddProfile':
updatedState = {...state, profiles: [...state.profiles, action.profile]}
break
case 'RemoveProfile':
updatedState = {
...state,
profiles: state.profiles.filter(
profile => profile.did !== action.profileDid,
),
}
break
case 'AddFeed':
updatedState = {...state, feedUris: [...state.feedUris, action.uri]}
break
case 'RemoveFeed':
updatedState = {
...state,
feedUris: state.feedUris.filter(uri => uri !== action.uri),
}
break
case 'SetProcessing':
updatedState = {...state, processing: action.processing}
break
}
switch (updatedState.currentStep) {
case 'Landing':
updatedState = {
...updatedState,
canNext: true,
}
break
case 'Details':
updatedState = {
...updatedState,
canNext: Boolean(updatedState.description),
}
break
}
return updatedState
}
// TODO supply the initial state to this component
export function Provider({
initialState,
initialStep = 'Landing',
children,
}: {
initialState?: any // TODO update this type
initialStep?: Step
children: React.ReactNode
}) {
const stateAndReducer = React.useReducer(
reducer,
initialState
? {
...initialState,
step: initialStep,
}
: {
canNext: true,
currentStep: initialStep,
profiles: [],
feedUris: [],
processing: false,
},
)
return (
<StateContext.Provider value={stateAndReducer}>
{children}
</StateContext.Provider>
)
}
export {
type Action as WizardAction,
type State as WizardState,
type Step as WizardStep,
}